<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>webcodr</title>
    <link>https://webcodr.io/topics/programming/</link>
    <description>Recent content on webcodr</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 28 May 2025 20:22:07 +0200</lastBuildDate>
    <atom:link href="https://webcodr.io/topics/programming/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Please don&#39;t do this with switch statements</title>
      <link>https://webcodr.io/2025/05/please-dont-do-this-with-switch-statements/</link>
      <pubDate>Wed, 28 May 2025 20:22:07 +0200</pubDate>
      <guid>https://webcodr.io/2025/05/please-dont-do-this-with-switch-statements/</guid>
      <description>The classic C-like switch statement is fine, but it has its flaws. It’s no coincidence that modern languages like Kotlin or Rust offer alternatives like when or match or a more fine-tuned version of switch like Zig.
I’m currently in the early stages of rewriting a large and complex Java code base to Kotlin. Some parts of this codebase are really ugly and unnecessarily complicated and convoluted. Yesterday I crossed the path of a nasty use of a switch statement in an operation on a Java Stream. Unfortunately I can’t share the real code, but imagine something like this:
</description>
      <content:encoded><![CDATA[<p>The classic C-like switch statement is fine, but it has its flaws. It&rsquo;s no coincidence that modern languages like Kotlin or Rust offer alternatives like <code>when</code> or <code>match</code> or a more fine-tuned version of <code>switch</code> like Zig.</p>
<p>I&rsquo;m currently in the early stages of rewriting a large and complex Java code base to Kotlin. Some parts of this codebase are really ugly and unnecessarily complicated and convoluted. Yesterday I crossed the path of a nasty use of a switch statement in an operation on a Java Stream. Unfortunately I can&rsquo;t share the real code, but imagine something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="n">value1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="n">value2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="p">(...)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="kd">enum</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="n">Enum</span><span class="p">.</span><span class="na">FOO</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">something</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">somethingElse</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">value1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">someConvolutedStreamOperations</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">value2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">someOtherConvolutedStreamOperations</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="c1">// imagine 30 more lines here</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">value2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="n">Enum</span><span class="p">.</span><span class="na">BAR</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">default</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">value1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">value2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This was part of a Java class with over 1,000 lines of code. Streams with many operations everywhere and sometimes very deep nesting thanks to old-style Java code. The original case for <code>Enum.FOO</code> stretches over almost the whole display space, so it&rsquo;s not easy to spot any potential pitfalls. After I ran IntelliJ&rsquo;s Kotlin migration tool and cleaned up all errors, it was time to run the unit tests and four out of 24 failed.</p>
<p>As you can imagine it&rsquo;s not straight forward to find problems in such a large and complex class but I came across a notice of an unused value assignment. Why it was there was also not clear immediately, so I compared the original Java file with the Kotlin version.</p>
<p>Since Kotlin has no <code>switch</code> IntelliJ converted it to <code>when</code>. Unlike its Java counterpart <code>when</code> can handle <code>null</code> and is exhaustive with enums. There is also no <code>break</code> keyword and that&rsquo;s exactly the problem here.</p>
<p>Look at the Java code and think about what happens on <code>Enum.FOO</code> if <code>something</code> is true but <code>somethingElse</code> isn&rsquo;t. The <code>break</code> keyword is not triggered and the <code>switch</code> statement goes on to the default block. As a result <code>value1</code> and <code>value2</code> are assigned their values.</p>
<p>IntelliJ&rsquo;s migration tool is quite good, but it didn&rsquo;t catch that and the generated <code>when</code> statement was wrong. That&rsquo;s also the reason for the unused assignment notice. I assume the migration tool was confused by the scope of <code>break</code> since both <code>switch</code> and <code>for</code> can use it. Also there is no real match in Kotlin for such a structure. You have to assign the values of both variables for every branch inside the <code>when</code> statement. After fixing that all tests ran successfully.</p>
<p>It&rsquo;s a really good example of how not to use <code>switch</code> statements, especially with nested control structures in a case. Since the original author of the code is no longer available, I can only guess why it was written this way. Probably to avoid duplication or even unintended. Well, it could seem as an elegant solution if you&rsquo;re familiar with the code, but to other people it&rsquo;s just an unnecessary pitfall that should be avoided. It&rsquo;s unintuitive at best, not easy to comprehend and can lead to nasty bugs, especially if it&rsquo;s unintended behaviour. That&rsquo;s why Kotlin, Rust, Zig and other modern languages avoid breaks in their alternatives to switch statements in the first place.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Micro DSLs for builders with Kotlin</title>
      <link>https://webcodr.io/2024/01/micro-dsls-for-builders-with-kotlin/</link>
      <pubDate>Fri, 19 Jan 2024 14:33:07 +0200</pubDate>
      <guid>https://webcodr.io/2024/01/micro-dsls-for-builders-with-kotlin/</guid>
      <description>The builder pattern is a great tool and it’s heavily used in many Java projects and dependencies. But in a Kotlin code base it looks a little odd and out-of-date. In this short post I will show you how to write a micro DSL on top of a builder with just a few lines of code.
I’m using Spring’s ResponseCookie class as base for the DSL as it has a builder already on-board.
</description>
      <content:encoded><![CDATA[<p>The builder pattern is a great tool and it&rsquo;s heavily used in many Java projects and dependencies. But in a Kotlin code base it looks a little odd and out-of-date. In this short post I will show you how to write a micro DSL on top of a builder with just a few lines of code.</p>
<p>I&rsquo;m using Spring&rsquo;s <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseCookie.html">ResponseCookie</a> class as base for the DSL as it has a builder already on-board.</p>
<p>A little example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">val</span> <span class="py">cookie</span> <span class="p">=</span> <span class="n">ResponseCookie</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">from</span><span class="p">(</span><span class="s2">&#34;cookie name&#34;</span><span class="p">,</span> <span class="s2">&#34;cookie value&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">httpOnly</span><span class="p">(</span><span class="k">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">path</span><span class="p">(</span><span class="s2">&#34;/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">build</span><span class="p">()</span>
</span></span></code></pre></div><p>What would this look like with a micro DSL?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">val</span> <span class="py">cookie</span> <span class="p">=</span> <span class="n">createCookie</span><span class="p">(</span><span class="s2">&#34;cookie name&#34;</span><span class="p">,</span> <span class="s2">&#34;cookie value&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">httpOnly</span><span class="p">(</span><span class="k">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">path</span><span class="p">(</span><span class="s2">&#34;/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Instead of calling the static method <code>ResponseCookie.from()</code> which returns a <code>ResponseCookieBuilder</code> object, you just give the function three parameters: two strings for name and value, and a trailing lambda with the builder context. There is also no need to call <code>ResponseCookieBuilder.build()</code> anymore. It&rsquo;s shorter and better to read. Since this is only a small example the advantages are not that big. Micro DSLs really shine with large and often used builders. They can also help to automate things, see below.</p>
<h2 id="how"><a href="#how" class="heading-anchor">How?</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">fun</span> <span class="nf">createCookie</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">name</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">    <span class="k">value</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">    <span class="n">lambda</span><span class="p">:</span> <span class="nc">ResponseCookieBuilder</span><span class="p">.()</span> <span class="o">-&gt;</span> <span class="n">Unit</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span> <span class="p">=</span> <span class="nc">ResponseCookie</span><span class="p">.</span><span class="n">from</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="k">value</span><span class="p">).</span><span class="n">apply</span><span class="p">(</span><span class="n">lambda</span><span class="p">).</span><span class="n">build</span><span class="p">()</span>
</span></span></code></pre></div><p>Et voila, a new micro DSL is born. Deriving the trailing lambda function from <code>ResponseCookieBuilder</code> does the trick. The lambda function takes an instance of <code>ResponseCookieBuilder</code> as context of <code>this</code>, so it&rsquo;s possible to access the methods of the given <code>ResponseCookieBuilder</code> inside the lambda function. All we have to do is to create an instance of <code>ResponseCookieBuilder</code> with <code>ResponseCookie.from()</code> and call Kotlin&rsquo;s apply method on the builder object with the lambda function. It will automatically inject the current instance of <code>ResponseCookieBuilder</code> into the lambda function and apply the instructions inside the lambda function on the instance. To create a <code>ResponseCookie</code> object from the builder, just call the build method and return the result.</p>
<p>You can use this little trick with all builders. Need more automation? No problem! In my current project we&rsquo;re using such micro DSLs to create product configurations. The factory method contains sanity checks after the lambda function was applied to the builder object. It will also fetch a YAML file via the product ID given to the builder. This data is parsed into an object and will be put into a property of the builder object. After the configuration object is created, the factory method will add it to a map and return the instance to store in a variable. It&rsquo;s now possible to directly access the configuration via its variable name or to fetch it from the map. The variable is very useful for tests, but if we have to fetch the configuration dynamically by ID from a string, the map is the way to go.</p>
<p>Of course there are other ways of achieving such automation, but the micro DSL approach is simple, improves readability and can also reduce redundant code. You can even easily nest builders to create a more powerful DSL. Spring&rsquo;s Kotlin extensions also rely on micro DSLs and extension functions. Take Spring Security for example. Their fluent interface for the security configuration is awful to read and difficult to understand, but Spring also provides a Kotlin extension with a micro DSL for that. So much more intuitive and better to read. There are many more extensions like for bean creation, the MVC mock in tests etc.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Why custom errors in JavaScript with Babel are broken</title>
      <link>https://webcodr.io/2018/04/why-custom-errors-in-javascript-with-babel-are-broken/</link>
      <pubDate>Fri, 27 Apr 2018 10:50:35 +0200</pubDate>
      <guid>https://webcodr.io/2018/04/why-custom-errors-in-javascript-with-babel-are-broken/</guid>
      <description>Have you ever tried to write a custom error class in JavaScript? Well, it does work to a certain extent. But if you want to add custom methods or call instanceof to determine the error type it will not work properly.
Here is a little example of a custom error class:
class MyError extends Error { constructor(foo = &#39;bar&#39;, ...params) { super(...params) if (Error.captureStackTrace) { Error.captureStackTrace(this, MyError) } this.foo = foo } getFoo() { return this.foo } } try { throw new MyError(&#39;myBar&#39;) } catch(e) { console.log(e instanceof MyError) // -&gt; false console.log(e.getFoo()) // -&gt; Uncaught TypeError: e.getFoo is not a function } Works fine in any browser with ES6/ES2015 support, but if you transpile the example with Babel to ES5 and execute the code, you will get the results shown in the comments.
</description>
      <content:encoded><![CDATA[<p>Have you ever tried to write a custom error class in JavaScript? Well, it does work to a certain extent. But if you want to add custom methods or call <code>instanceof</code> to determine the error type it will not work properly.</p>
<p>Here is a little example of a custom error class:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">MyError</span> <span class="kr">extends</span> <span class="nb">Error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">constructor</span><span class="p">(</span><span class="nx">foo</span> <span class="o">=</span> <span class="s1">&#39;bar&#39;</span><span class="p">,</span> <span class="p">...</span><span class="nx">params</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">super</span><span class="p">(...</span><span class="nx">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nb">Error</span><span class="p">.</span><span class="nx">captureStackTrace</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nb">Error</span><span class="p">.</span><span class="nx">captureStackTrace</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">MyError</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">foo</span> <span class="o">=</span> <span class="nx">foo</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="nx">getFoo</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">foo</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">throw</span> <span class="k">new</span> <span class="nx">MyError</span><span class="p">(</span><span class="s1">&#39;myBar&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">e</span> <span class="k">instanceof</span> <span class="nx">MyError</span><span class="p">)</span> <span class="c1">// -&gt; false
</span></span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">getFoo</span><span class="p">())</span> <span class="c1">// -&gt; Uncaught TypeError: e.getFoo is not a function
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Works fine in any browser with ES6/ES2015 support, but if you transpile the example with Babel to ES5 and execute the code, you will get the results shown in the comments.</p>
<h2 id="why"><a href="#why" class="heading-anchor">Why</a></h2>
<p>Due to limitations of ES5 it&rsquo;s not possible to inherit from built-in classes like <code>Error</code>, see the <a href="https://babeljs.io/docs/usage/caveats/#classes">Babel docs</a>.</p>
<h3 id="possible-solution"><a href="#possible-solution" class="heading-anchor">Possible solution</a></h3>
<p>The docs mention a plug-in called <code>babel-plugin-transform-builtin-extend</code> to resolve this issue, but if you have to support older browsers it may not help. In order to work the plug-in needs support for <code>__proto__</code>. Take a guess which browser does not support <code>__proto__</code> &hellip; and of course, it&rsquo;s the web developer&rsquo;s best friend aka Internet Explorer. Thankfully it affects only version 10 and below.</p>
<h3 id="workaround"><a href="#workaround" class="heading-anchor">Workaround</a></h3>
<p>If it&rsquo;s not feasible to use the plug-in, you can at least access properties set in the constructor. A call to <code>e.foo</code> in the example is possible, but <code>e instanceof MyError</code> will return <code>false</code>, since you will always get an instance of <code>Error</code>.</p>
<h2 id="conclusion"><a href="#conclusion" class="heading-anchor">Conclusion</a></h2>
<p>Nothing of this is ideal. We have to wait until it&rsquo;s possible to use ES6/ES2015 directly. Yes, we all could set our transpile targets to ES6/ES2015 today, but our clients usually won&rsquo;t allow it. Some customer is always browsing the web with an ancient device/browser.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Amplify 2.0</title>
      <link>https://webcodr.io/2013/07/amplify-2.0/</link>
      <pubDate>Sat, 27 Jul 2013 22:30:36 +0100</pubDate>
      <guid>https://webcodr.io/2013/07/amplify-2.0/</guid>
      <description>Ich habe Amplify grundlegend überarbeitet und mit ein paar neuen Features ausgestattet:
Redcarpet wurde durch kramdown ersetzt und unterstützt damit auch die Markdown-Erweiterungen, die kramdown anbietet. Automatisches Verlinken von URLs HTML-Sanitation Das Syntax-Highlighting übernimmt nun das Gem ‘pygments.rb’. Der Umweg über Pygmentizr fällt damit intern weg und verbessert die Reaktionszeiten deutlich. Das Frontend basiert nun auf AngularJS. Komplett überarbeiteter Quelltext. JSON-basierte API kramdown, das automatische Verlinken und die HTML-Sanitation werden über das Gem ‘slodown’ von Hendrik Mans erledigt.
</description>
      <content:encoded><![CDATA[<p>Ich habe Amplify grundlegend überarbeitet und mit ein paar neuen Features ausgestattet:</p>
<ul>
<li>Redcarpet wurde durch kramdown ersetzt und unterstützt damit auch die Markdown-Erweiterungen, die kramdown anbietet.</li>
<li>Automatisches Verlinken von URLs</li>
<li>HTML-Sanitation</li>
<li>Das Syntax-Highlighting übernimmt nun das Gem &lsquo;pygments.rb&rsquo;. Der Umweg über Pygmentizr fällt damit intern weg und verbessert die Reaktionszeiten deutlich.</li>
<li>Das Frontend basiert nun auf AngularJS.</li>
<li>Komplett überarbeiteter Quelltext.</li>
<li>JSON-basierte API</li>
</ul>
<p>kramdown, das automatische Verlinken und die HTML-Sanitation werden über das Gem &lsquo;<a href="https://github.com/hmans/slodown">slodown</a>&rsquo; von Hendrik Mans erledigt.</p>
<p>Die neue JSON-basierte API ist über eine andere URL erreichbar:</p>
<p><code>http://amplify.webcodr.de/api/2.0/transform</code></p>
<p>Ein Beispiel-Request via POST:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;source&#34;</span><span class="p">:</span> <span class="s2">&#34;# Hello World!&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Und die entsprechende Antwort von Amplify:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">&#34;html&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;h1 id=\&#34;hello-world\&#34;&gt;Hello World!&lt;/h1&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;source&#34;</span><span class="p">:</span> <span class="s2">&#34;# Hello World!&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Wer, wie früher, ohne JSON auskommen möchte, nutzt bitte folgende URL:</p>
<p><code>http://amplify.webcodr.de/api/1.0/transform</code></p>
<p>Die bisherige Möglichkeit einfach einen POST-Request auf die Amplify-URL abzusetzen ist nur noch aus Gründen der Kompatibilität zu bestehenden Anwendungen aktiv, wird aber langfristig deaktiviert.</p>
<p>Zukünftige Features werde ich außerdem nur für die JSON-basierte API 2.0 implementieren.</p>
<p>Des weiteren plane ich Amplify langfristig nicht mehr auf Heroku laufen zu lassen, da die App einfach zu häufig in den Schlafmodus versetzt wird und anschließend sehr lange braucht, bis sie auf Anfragen reagiert.</p>
<p>Ich könnte zwar einfach einen Dyno hinzubuchen, aber das ist nicht gerade billig und es gibt wirklich kostengünstigere Möglichkeiten, Ruby-Web-Applikationen zu hosten &ndash; beispielsweise bei <a href="https://uberspace.de/">Uberspace.de</a>.</p>
<p>Aus technischer Sicht dürfte noch interessant sein, dass Amplify nun mit Capybara automatisiert getestet wird und auf <a href="https://travis-ci.org/WebCodr/Amplify">Travis CI</a> sowie testweise <a href="https://circleci.com/">Circle CI</a> (mit automatischem Heroku-Deployment) läuft.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Say Hello to Mango</title>
      <link>https://webcodr.io/2013/04/say-hello-to-mango/</link>
      <pubDate>Sat, 06 Apr 2013 22:29:53 +0100</pubDate>
      <guid>https://webcodr.io/2013/04/say-hello-to-mango/</guid>
      <description>Was’n das? Finger weg! Diese Mango schmeckt nicht.
Mango ist ein Object Document Mapper für MongoDB und PHP.
Und MongoAppKit? MongoAppKit hat ein Problem, denn es ist nicht nur ein ODM und kann noch so einiges mehr. Theoretisch kann man zwar die ODM-Komponente auch ohne den ganzen anderen Krempel nutzen, aber es bleibt eine große Abhängigkeit zu Silex, die man auch nicht so einfach wieder los wird.
Dies und das im Vergleich schlechte Handling bzw. der geringe Komfort von MongoAppKit, haben mich dazu bewogen mit Mango einen universell einsatzbaren und leicht handzuhabenden ODM zu entwickeln.
</description>
      <content:encoded><![CDATA[<h2 id="wasn-das"><a href="#wasn-das" class="heading-anchor">Was&rsquo;n das?</a></h2>
<p>Finger weg! Diese Mango schmeckt nicht.</p>
<p>Mango ist ein Object Document Mapper für MongoDB und PHP.</p>
<h3 id="und-mongoappkit"><a href="#und-mongoappkit" class="heading-anchor">Und MongoAppKit?</a></h3>
<p>MongoAppKit hat ein Problem, denn es ist nicht nur ein ODM und kann noch so einiges mehr. Theoretisch kann man zwar die ODM-Komponente auch ohne den ganzen anderen Krempel nutzen, aber es bleibt eine große Abhängigkeit zu Silex, die man auch nicht so einfach wieder los wird.</p>
<p>Dies und das im Vergleich schlechte Handling bzw. der geringe Komfort von MongoAppKit, haben mich dazu bewogen mit Mango einen universell einsatzbaren und leicht handzuhabenden ODM zu entwickeln.</p>
<p>Mango wurde stark von Mongoid für Ruby inspiriert und soll dessen Funktionalität zumindest teilweise in PHP abbilden. Das ist einfacher gesagt als getan, denn Ruby bietet wesentlich elegantere Möglichkeiten diverse Probleme zu lösen, als es mit PHP derzeit machbar ist.</p>
<h2 id="los-gehts-"><a href="#los-gehts-" class="heading-anchor">Los geht&rsquo;s …</a></h2>
<h3 id="installation-via-composer"><a href="#installation-via-composer" class="heading-anchor">Installation via Composer</a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">php composer.phar require webcodr/mango:*
</span></span></code></pre></div><h3 id="ein-dokument-anzulegen-ist-ein-kinderspiel"><a href="#ein-dokument-anzulegen-ist-ein-kinderspiel" class="heading-anchor">Ein Dokument anzulegen ist ein Kinderspiel</a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">namespace</span> <span class="nx">MyProject\Model</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">Mango\Document</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">Mango\DocumentInterface</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">User</span> <span class="k">implements</span> <span class="nx">DocumentInterface</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">use</span> <span class="nx">Document</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">private</span> <span class="k">function</span> <span class="nf">addFields</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addField</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;String&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addField</span><span class="p">(</span><span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;String&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addField</span><span class="p">(</span><span class="s1">&#39;created_at&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;DateTime&#39;</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span> <span class="s1">&#39;default&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;now&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">addField</span><span class="p">(</span><span class="s1">&#39;updated_at&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;DateTime&#39;</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span> <span class="s1">&#39;default&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;now&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Es ist lediglich nötig, dass die Model-Klasse das Interface <code>DocumentInterface</code> implementiert und den Trait <code>Document</code> einbindet. In der Hook-Methode <code>addFields()</code> werden anschließend noch die Felder des Dokuments deklariert.</p>
<p>Mango nutzt etwas Magic: Der Klassenname des Models ist gleichzeitig auch der Name der Collection (klein geschrieben). Soll die Collection anders heißen bzw. das Model eine vorhandene nutzen, muss lediglich die Methode <code>getCollectionName()</code> überschrieben werden.</p>
<h3 id="go-mango-go"><a href="#go-mango-go" class="heading-anchor">Go, Mango, go</a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">Mango\Mango</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">Mango\DocumentManager</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">Document\User</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$mango</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Mango</span><span class="p">(</span><span class="s1">&#39;mongodb://localhost/galactica&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$dm</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DocumentManager</span><span class="p">(</span><span class="nv">$mango</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">User</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nv">$user</span><span class="o">-&gt;</span><span class="na">name</span> <span class="o">=</span> <span class="s1">&#39;William Adama&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$user</span><span class="o">-&gt;</span><span class="na">email</span> <span class="o">=</span> <span class="s1">&#39;william.adama@bsg-75.mil&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$user</span><span class="o">-&gt;</span><span class="na">store</span><span class="p">();</span>
</span></span></code></pre></div><p>Das Mango-Object erwartet eine gültige MongoDB URI, falls notwendig inkl. Benutzer, Passwort, Port usw.</p>
<p>Dem Document Manager kommt eine vergleichbare Aufgabe zu, wie dem Entity Manager in Doctrine2.</p>
<p>Für mehr Komfort holt sich eine Model-Klasse den Document Manager über eine statische Methode ab. Daher können Methoden wie <code>store()</code> direkt über die Model-Klasse abgewickelt werden.</p>
<h3 id="dokumente-abfragen"><a href="#dokumente-abfragen" class="heading-anchor">Dokumente abfragen</a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$user</span> <span class="o">=</span> <span class="nx">User</span><span class="o">::</span><span class="na">where</span><span class="p">([</span><span class="s1">&#39;name&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;William Adama&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="k">echo</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="na">count</span><span class="p">();</span> <span class="c1">// = 1
</span></span></span><span class="line"><span class="cl"><span class="k">echo</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="na">first</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">email</span><span class="p">;</span> <span class="c1">// = william.adama@bsg-75.mil
</span></span></span></code></pre></div><p>Eine Abfrage kann einfach über die statische Methode <code>where()</code> ausgeführt werden. Die Syntax der Abfragen entspricht derzeit noch der normalen MongoDB Query API. Für die Zukunft plane ich aber eine Abstraktionsebene für die Abfragen, vergleichbar mit Mongoid.</p>
<p>Eine Abfrage mit <code>where()</code> oder <code>find()</code> gibt immer ein Cursor-Objekt zurück, das anhand der aufgerufenen Methode entscheiden kann, ob der Zugriff auf den MongoCursor oder das Abfrageergebnis in Form einer Instanz von MutableMap erfolgt.</p>
<p>In obigem Beispiel ist <code>count()</code> eine Methode des Cursors, während <code>first()</code> schon auf das Ergebnis zugreift. Wie MongoCursor kann auch die Cursor-Klasse von Mango einfach über das Ergebnis iterieren.</p>
<p>Durch die dynamische Unterscheidung zwischen MongoCursor- und Datenzugriff, können auf eine Instanz der Cursor-Klasse auch alle Methoden von MutableMap angewandt werden.</p>
<p>Beispielsweise:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">User</span><span class="o">::</span><span class="na">where</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">reverse</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">each</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="nv">$document</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">echo</span> <span class="nv">$document</span><span class="o">-&gt;</span><span class="na">name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Natürlich macht dieser Code wenig Sinn, da man das wesentlich effizienter über die Cursor-Methoden erledigen kann. Das Beispiel soll lediglich zeigen, was möglich wäre.</p>
<h3 id="hydration"><a href="#hydration" class="heading-anchor">Hydration</a></h3>
<p>Mango sorgt automatisch dafür, dass die Dokumente im Ergebnis immer Instanzen ihrer jeweiligen Model-Klasse sind.</p>
<p>Die Hydration-Automatik sorgt außerdem dafür, dass die Daten intern als jeweilige Typ-Klasse von Mango gehalten werden.</p>
<p>Typ-Klassen halten die Daten und können sie in zwei Formaten zurückgeben. Konfiguriert man ein Feld als <code>DateTime</code> bekommt Mango intern beim Speichern automatisch ein MongoDate-Objekt. Greift man hingegen außerhalb von Mango auf den Wert zu, bekäme man in diesem Fall eine Instanz der Klasse DateTime zurück.</p>
<p>Soweit zum aktuellen Funktionsumfang von Mango. Es ist bei weitem noch nicht fertig, kann aber für kleine Projekte schon eingesetzt werden. Ich verwende es selbst in der aktuellsten Version von CodrPress und es macht wesentlich mehr Spaß als MongoAppKit, ohne ein monströses Schlachtschiff wie Doctrine zu sein.</p>
<p>Natürlich gibt&rsquo;s Mango auch bei <a href="https://github.com/WebCodr/Mango">GitHub</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Services ftw!</title>
      <link>https://webcodr.io/2013/02/services-ftw/</link>
      <pubDate>Sat, 02 Feb 2013 22:29:07 +0100</pubDate>
      <guid>https://webcodr.io/2013/02/services-ftw/</guid>
      <description>Wer kennt das nicht? Man findet eine nette Software-Bibliothek in einer bestimmten Sprache, die vom Server der eigenen Web-Applikation nicht unterstützt wird oder nur sehr umständlich auf andere Weise genutzt werden kann.
So erging es mir mit Tools für Markdown-Rendering und server-basiertem Syntax-Highlighting. Zwar habe ich dafür ja im Oktober die Composer-Pakete SilexMarkdown und Radiant geschrieben, die beide auf bereits vorhandenen Bibliotheken fußen.
Ich war mit beiden nie recht glücklich. Für Ruby und Python gibt es viel schönere, wesentlich umfangreichere Lösungen:
</description>
      <content:encoded><![CDATA[<p>Wer kennt das nicht? Man findet eine nette Software-Bibliothek in einer bestimmten Sprache, die vom Server der eigenen Web-Applikation nicht unterstützt wird oder nur sehr umständlich auf andere Weise genutzt werden kann.</p>
<p>So erging es mir mit Tools für Markdown-Rendering und server-basiertem Syntax-Highlighting. Zwar habe ich dafür ja im Oktober die Composer-Pakete SilexMarkdown und Radiant geschrieben, die beide auf bereits vorhandenen Bibliotheken fußen.</p>
<p>Ich war mit beiden nie recht glücklich. Für Ruby und Python gibt es viel schönere, wesentlich umfangreichere Lösungen:</p>
<ul>
<li>
<p>Pygments ist ein in Python geschriebener Syntax-Highlighter, der nahezu jede relevante Sprache unterstützt &ndash; selbst esoterische Merkwürdigkeiten wie Brainfuck.</p>
</li>
<li>
<p>Redcarpet wurde in Ruby verfasst und bietet einen sehr leicht erweiter- und modifizierbaren Markdown-Renderer.</p>
</li>
</ul>
<p>Gerade für ein Blog-System wie CodrPress liegt es nahe, beide zu kombinieren und damit zumindest teilweise GitHub flavoured Markdown zu unterstützen.</p>
<p>Wie bekomme ich also drei Programmiersprachen unter einen Hut, ohne dass CodrPress nur auf angepassten Server-Konfigurationen läuft? Ganz einfach: Services!</p>
<h2 id="pygmentizr"><a href="#pygmentizr" class="heading-anchor">Pygmentizr</a></h2>
<p><a href="https://web.archive.org/web/20140516204904/http://pygmentizr.herokuapp.com/">Pygmentizr</a> ist logischerweise in Python geschrieben, um Pygments nutzen zu können.</p>
<p>Per POST-Anfrage auf die verlinkte URL erreicht man den eigentlichen Service, der als Parameter die Sprache und den Quelltext erwartet. Zurück kommt HTML, das nur noch per CSS hübsch gemacht werden muss.</p>
<p>Ein entsprechendes Stylesheet für den bekannten Monokai-Stil ist auf der Seite verlinkt oder im GitHub-Repository zu finden.</p>
<p><a href="https://web.archive.org/web/20131210082228/https://github.com/MadCatme/Pygmentizr">Pygmentizr bei GitHub</a></p>
<h2 id="amplifyr"><a href="#amplifyr" class="heading-anchor">Amplifyr</a></h2>
<p>Amplifyr nutzt Redcarpet und bindet Pygmentizr als Syntax-Highlighter ein.</p>
<p>Wie Pygmentizr lässt sich Amplifyr per POST-Anfrage ansprechen und gibt den in HTML konvertierten Markdown-Quelltext zurück.</p>
<p>Beide Dienste laufen auf der Cloud-Plattform Heroku.</p>
<h2 id="codrpress-integration"><a href="#codrpress-integration" class="heading-anchor">CodrPress-Integration</a></h2>
<p>Um beide Services in CodrPress nutzen zu können, habe ich in SilexMarkdown ein paar Umbauten vorgenommen. Beim Registrieren des Service-Providers in einer Silex-Applikation, lässt sich nun ganz einfach übergeben, ob der eingebaute Renderer samt Radiant oder Amplifyr genutzt werden soll. Eine entsprechende Anleitung findet sich in der ReadMe-Datei des SilexMarkdown-Repositories bei GitHub.</p>
<p>Beide Dienste sind bei Heroku untergebracht und kosten mich keinen Cent. Daher gebe ich die Nutzung für jeden frei. Viel Spaß!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Array almighty</title>
      <link>https://webcodr.io/2013/02/array-almighty/</link>
      <pubDate>Sat, 02 Feb 2013 22:28:05 +0100</pubDate>
      <guid>https://webcodr.io/2013/02/array-almighty/</guid>
      <description>Wenn man sich zu lange nur mit PHP beschäftigt vergisst man schnell, dass man oft Dinge tut, die kaum in andere Sprachen übertragbar sind.
Letztens habe ich mir Scala etwas näher angesehen. Kurz am Rande: eine schöne Sprache, wenn auch die verschiedenen Syntax-Modi etwas verwirrend oder zumindest recht gewöhnungsbedürftig sind.
Vorteil PHP Scala bietet wie fast jede andere typisierte Sprache verschiedene Listen-Klassen für diverse Nutzungsfälle. In PHP gibt es das nicht. Man hat sein Array, das jederzeit veränderlich ist, jede noch so wilde Mischung von Datentypen akzeptiert und assoziative Schlüssel erlaubt. Es ist einfach ungemein praktisch.
</description>
      <content:encoded><![CDATA[<p>Wenn man sich zu lange nur mit PHP beschäftigt vergisst man schnell, dass man oft Dinge tut, die kaum in andere Sprachen übertragbar sind.</p>
<p>Letztens habe ich mir Scala etwas näher angesehen. Kurz am Rande: eine schöne Sprache, wenn auch die verschiedenen Syntax-Modi etwas verwirrend oder zumindest recht gewöhnungsbedürftig sind.</p>
<h2 id="vorteil-php"><a href="#vorteil-php" class="heading-anchor">Vorteil PHP</a></h2>
<p>Scala bietet wie fast jede andere typisierte Sprache verschiedene Listen-Klassen für diverse Nutzungsfälle. In PHP gibt es das nicht. Man hat sein Array, das jederzeit veränderlich ist, jede noch so wilde Mischung von Datentypen akzeptiert und assoziative Schlüssel erlaubt. Es ist einfach ungemein praktisch.</p>
<h2 id="vorteil-scala"><a href="#vorteil-scala" class="heading-anchor">Vorteil Scala</a></h2>
<p>Da PHP leider weit davon entfernt ist vollständig objekt-orientiert zu sein und darum ein Array leider kein Objekt ist, kann man Arrays nur mit diversen Funktionen bearbeiten.</p>
<p>Zwar funktioniert das einwandfrei, ist aber umständlich. Ein Array-Objekt, das entsprechende Methoden bietet, die sich am besten auch noch verkettet aufrufen lassen, wäre doch toll.</p>
<h2 id="php-goes-scalajavaobjective-c"><a href="#php-goes-scalajavaobjective-c" class="heading-anchor">PHP goes Scala/Java/Objective-C</a></h2>
<p>Daher habe ich mich ans Werk gemacht und die bereits existierende Klasse <code>IterateableList</code> in MongoAppKit in drei neue Klassen des Namespaces <code>\MongoAppKit\Collection</code> aufgeteilt: <code>MutableMap</code> und <code>ArrayMap</code>.</p>
<p>Die Namen orientieren sich an ihren Pendants in Scala, Java oder auch Objective-C. Während alle die SPL-Interfaces <code>Countable</code> und <code>IteratorAggregate</code> implementieren, verwendet <code>ArrayMap</code> zusätzlich das Interface <code>ArrayAccess</code> und kann damit wie ein PHP-Array verwendet werden.</p>
<p>Außerdem implementieren alle drei die Magic Methods <code>__get()</code>, <code>__set()</code>, <code>__isset()</code> und <code>__unset</code>. Das erleichtert z.B. die Verwendung einer Liste in Twig, in dem keine Methode mehr angesprochen werden muss, um innerhalb eines Templates auf die Inhalte zuzugreifen.</p>
<p>Um diverse Array-Funktionen von PHP abzubilden implementieren alle drei die Methoden:</p>
<ul>
<li><code>first()</code>: gibt das erste Element der Liste zurück</li>
<li><code>last()</code>: gibt das letzte Element der Liste zurück</li>
<li><code>reverse()</code>: dreht die Reihenfolge der Elemente innerhalb der Liste um</li>
<li><code>each()</code>: wendet eine Callback-Funktion mittels <code>array_walk</code> auf alle Elemente an, in der auch auf die Schlüssel zugegriffen werden kann</li>
<li><code>map()</code>: wendet eine Callback-Funktion mittels <code>array_map</code> auf alle Elemente an</li>
<li><code>slice()</code>: schneidet einen Teil der Elemente heraus und gibt sie in einem neuen Listen-Objekt zurück</li>
<li><code>filter()</code>: filtert die Elemente einer Liste anhand einer Callback-Funktion und gibt das Ergebnis in einem neuen Listen-Objekt zurück</li>
</ul>
<h2 id="fluent-interface"><a href="#fluent-interface" class="heading-anchor">Fluent Interface</a></h2>
<p>Um eine Verkettung von Methodenaufrufen zu ermöglichen gibt jede Methode, die sonst keinen Rückgabewert hätte, eine Referenz auf ihre Klasse zurück. Nur <code>slice()</code> und <code>filter()</code> geben eine neue Liste mit den herausgeschnittenen bzw. gefilterten Werten zurück.</p>
<p>Hier ein kleines Beispiel aus CodrPress, was man damit alles anstellen kann:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Post</span><span class="o">::</span><span class="na">where</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">each</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="nv">$document</span><span class="p">)</span> <span class="k">use</span> <span class="p">(</span><span class="nv">$app</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$md</span> <span class="o">=</span> <span class="nv">$document</span><span class="o">-&gt;</span><span class="na">getProperty</span><span class="p">(</span><span class="s1">&#39;body&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$html</span> <span class="o">=</span> <span class="nv">$app</span><span class="p">[</span><span class="s1">&#39;markdown&#39;</span><span class="p">]</span><span class="o">-&gt;</span><span class="na">transform</span><span class="p">(</span><span class="nv">$md</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$document</span><span class="o">-&gt;</span><span class="na">set</span><span class="p">(</span><span class="s1">&#39;body_html&#39;</span><span class="p">,</span> <span class="nv">$html</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Die statische Methode <code>Post::where()</code> liefert ohne Query alle Posts als MutableMap-Objekt zurück. Auf die Rückgabe lässt sich sofort <code>each()</code> anwenden, das alle Elemente der Liste iteriert und die definierte Closure auf jedes Element einzeln anwendet.</p>
<p>In diesem Fall wird das rohe Markdown aus dem Feld <code>body</code> in HTML transformiert und im Feld <code>body_html</code> abgespeichert.</p>
<h2 id="fazit"><a href="#fazit" class="heading-anchor">Fazit</a></h2>
<p><code>MutableMap</code> und seine Sub-Klassen sparen viel Schreibarbeit durch ein simples und komfortables Fluent Interface &ndash; eine Vorgehensweise, der in PHP leider viel zu wenig Beachtung geschenkt wird.</p>
<h2 id="download"><a href="#download" class="heading-anchor">Download</a></h2>
<p>Die drei Klassen sind nicht länger Teil von MongoAppKit. Ich habe sie in ein separates <a href="https://github.com/WebCodr/Collection">GitHub-Repository</a> und <a href="https://packagist.org/packages/webcodr/collection">Composer-Paket</a> ausgelagert, um eine unkomplizierte Nutzung ohne MongoAppKit zu ermöglichen. Viel Spaß!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>PythonPress</title>
      <link>https://webcodr.io/2012/12/pythonpress/</link>
      <pubDate>Sun, 02 Dec 2012 22:27:13 +0100</pubDate>
      <guid>https://webcodr.io/2012/12/pythonpress/</guid>
      <description>Da eine neue Sprache nicht genug ist, beschäftige ich mich neben Ruby neuerdings auch noch mit Python.
Als Lernprojekt setze ich aktuell CodrPress als Python-Version um. Natürlich will ich nicht das Rad neu erfinden, daher setze ich auf zwei Frameworks, dank denen ich sehr schnell ein vorzeigbares Ergebnis zusammenbauen konnte:
Flask ist ein Micro-Framework vergleichbar mit Sinatra (Ruby) oder Silex (PHP). Es kümmert sich also um alles, was man braucht, um eine Website zu bauen. Vom Routing bis hin zur Template Engine (Jinja2).
</description>
      <content:encoded><![CDATA[<p>Da eine neue Sprache nicht genug ist, beschäftige ich mich neben Ruby neuerdings auch noch mit Python.</p>
<p>Als Lernprojekt setze ich aktuell CodrPress als Python-Version um. Natürlich will ich nicht das Rad neu erfinden, daher setze ich auf zwei Frameworks, dank denen ich sehr schnell ein vorzeigbares Ergebnis zusammenbauen konnte:</p>
<ul>
<li>
<p><a href="http://flask.pocoo.org/">Flask</a> ist ein Micro-Framework vergleichbar mit Sinatra (Ruby) oder Silex (PHP). Es kümmert sich also um alles, was man braucht, um eine Website zu bauen. Vom Routing bis hin zur Template Engine (Jinja2).</p>
</li>
<li>
<p><a href="http://mongoengine.org/">MongoEngine</a> bietet einen ODM (Object Document Mapper) vergleichbar mit Mongoid (Ruby) oder meinem eigenen Projekt MongoAppKit in PHP.</p>
</li>
</ul>
<h2 id="routen-definitionen-mit-flask"><a href="#routen-definitionen-mit-flask" class="heading-anchor">Routen-Definitionen mit Flask</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@app.route</span><span class="p">(</span><span class="s1">&#39;/hello/&lt;name&gt;&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="s1">&#39;Hello </span><span class="si">%s</span><span class="s1">!&#39;</span> <span class="o">%</span> <span class="n">name</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</span></span></code></pre></div><p>Zu Beginn wird die Klasse <code>Flask</code> aus dem Package <code>flask</code> importiert und anschließend eine Instanz erstellt.</p>
<p>Im Gegensatz zu PHP oder anderen C-Syntax-Sprachen kennt Python das Schlüsselwort new nicht. Um ein neues Objekt zu instanziieren reicht es den Klassennamen samt den Klammern und ggf. den Constructor-Argumenten zu schreiben.</p>
<p>Es folgt die Routen-Definition. Variable Werte werden in spitze Klammern gesetzt und der anschließenden Methode mit gleichem Namen als Parameter übergeben.</p>
<p>Wie auch in Silex oder Sinatra wird der Rückgabewert einer Routen-Methode zurück an den Browser geschickt. In diesem Fall ist das nur ein simpler String-Wert.</p>
<h2 id="templates-in-flask"><a href="#templates-in-flask" class="heading-anchor">Templates in Flask</a></h2>
<p>Flask nutzt die Template Engine Jinja2. Wer aus der PHP-Welt Twig kennt fühlt sich sofort heimisch. Die Sprachelemente sind nahezu identisch.</p>
<p>Datei: <code>./templates/hello.html</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Hello {{ name }}!<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>  
</span></span></code></pre></div><p>In obiger Route müsste die Methode nun so aussehen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">render_template</span>
</span></span><span class="line"><span class="cl"><span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;hello.html&#39;</span><span class="p">,</span> <span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">...</span>
</span></span></code></pre></div><p>Nicht vergessen: <code>render_template</code> muss zusätzlich importiert werden!</p>
<h2 id="mongoengine"><a href="#mongoengine" class="heading-anchor">MongoEngine</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mongoengine</span> <span class="kn">import</span> <span class="o">*</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">connect</span><span class="p">(</span><span class="s1">&#39;test&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Post</span><span class="p">(</span><span class="n">Document</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">_id</span> <span class="o">=</span> <span class="n">ObjectIdField</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">created_at</span> <span class="o">=</span> <span class="n">DateTimeField</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">published</span> <span class="o">=</span> <span class="n">BooleanField</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">title</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">body</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">()</span>
</span></span></code></pre></div><p>Der Aufruf von <code>connect</code> stellt eine Verbindung zur Datenbank <code>test</code> her. Da keine Verbindungsdaten angegeben werden, geht MongoEngine automatisch von einem lokalen MongoDB-Server auf dem Standard-Port aus.</p>
<p>Die Klasse <code>Post</code> ist eine Sub-Klasse von <code>Document</code> aus MongoEngine. Anschließend werden die Felder der Klasse definiert. MongoEngine stellt für jeden von MongoDB unterstützten Datentyp entsprechende Klassen zur Verfügung.</p>
<p>Sofern nicht über das Attribut <code>meta</code> eine andere Collection definiert wird, greift MongoEngine auf den Klassennamen in Kleinbuchstaben als Collection zu.</p>
<p>Um ein neues Dokument von Post zu erstellen und zu speichern, reicht schon folgender Code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">post</span> <span class="o">=</span> <span class="n">Post</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">post</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl"><span class="n">post</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s1">&#39;Hello World!&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">post</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="s1">&#39;Hallo, ich bin ein Test.&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">post</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</span></span></code></pre></div><h2 id="abfragen-mit-mongoengine"><a href="#abfragen-mit-mongoengine" class="heading-anchor">Abfragen mit MongoEngine</a></h2>
<p>Als vollständiger ODM bietet MongoEngine natürlich auch die Möglichkeit vorhandene Daten abzufragen. In folgendem Beispiel werden die letzten zehn veröffentlichten Einträge absteigend nach dem Erstelldatum sortiert, in ein Array geschrieben.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">posts</span> <span class="o">=</span> <span class="n">Post</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">published</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-created_at&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span></code></pre></div><p>Abfragen erfolgen statisch, daher ist keine Instanz nötig. Die Methode <code>objects()</code> enthält die Bedingungen, also in diesem Fall, dass ein Eintrag veröffentlicht wurde. <code>order_by()</code> erwartet den Feldnamen mit der Sortierrichtung als Präfix. Hierbei steht <code>+</code> für aufsteigend und <code>-</code> für absteigend. Zu guter Letzt wird das Ergebnis mit <code>limit()</code> auf 10 Dokumente eingeschränkt.</p>
<p>Mit diesem Wissen lässt sich nun ganz schnell eine Basis-Applikation bauen, die aus der vorhandenen CodrPress-Collection Einträge ausliest und anzeigt.</p>
<p>Der bisherige Stand ist natürlich bei <a href="https://web.archive.org/web/20131210082353/https://github.com/MadCatme/CodrPressP">GitHub</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Menlo Park, start your photocopiers ...</title>
      <link>https://webcodr.io/2012/08/menlo-park-start-your-photocopiers/</link>
      <pubDate>Fri, 24 Aug 2012 22:25:16 +0100</pubDate>
      <guid>https://webcodr.io/2012/08/menlo-park-start-your-photocopiers/</guid>
      <description>… oder warum Software-Patente und Patentkriege scheiße sind Gestern habe ich für die Share-Funktionen von Twitter, Google+ und Facebook jeweils ein Modul nach dem CommonJS-Standard gebaut, um sie in meinem privaten Weblog zu nutzen.
Daran ist nun nichts Besonderes, wenn ich nicht eine kleine Entdeckung gemacht hätte. Offenbar hat Facebook den nötigen JavaScript-Code von Twitter kopiert oder Twitter von Facebook.
Quelltext vom Twitter !function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if(!d.getElementById(id)) { js = d.createElement(s); js.id = id; js.src = &#34;//platform.twitter.com/widgets.js&#34;; fjs.parentNode.insertBefore(js, fjs); } }(document, &#34;script&#34;, &#34;twitter-wjs&#34;); Quelltext von Facebook (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if(d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = &#34;//connect.facebook.net/de_DE/all.js#xfbml=1&#34;; fjs.parentNode.insertBefore(js, fjs); }(document, &#39;script&#39;, &#39;facebook-jssdk&#39;)); Zwecks der Lesbarkeit habe ich die Funktionen entsprechend formatiert.
</description>
      <content:encoded><![CDATA[<h2 id="-oder-warum-software-patente-und-patentkriege-scheiße-sind"><a href="#-oder-warum-software-patente-und-patentkriege-schei%c3%9fe-sind" class="heading-anchor">&hellip; oder warum Software-Patente und Patentkriege scheiße sind</a></h2>
<p>Gestern habe ich für die Share-Funktionen von Twitter, Google+ und Facebook jeweils ein Modul nach dem <a href="http://www.commonjs.org/">CommonJS-Standard</a> gebaut, um sie in meinem privaten Weblog zu nutzen.</p>
<p>Daran ist nun nichts Besonderes, wenn ich nicht eine kleine Entdeckung gemacht hätte. Offenbar hat Facebook den nötigen JavaScript-Code von Twitter kopiert oder Twitter von Facebook.</p>
<h2 id="quelltext-vom-twitter"><a href="#quelltext-vom-twitter" class="heading-anchor">Quelltext vom Twitter</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="o">!</span><span class="kd">function</span><span class="p">(</span><span class="nx">d</span><span class="p">,</span> <span class="nx">s</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">fjs</span> <span class="o">=</span> <span class="nx">d</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="nx">s</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">d</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">id</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">js</span> <span class="o">=</span> <span class="nx">d</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">js</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">js</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="s2">&#34;//platform.twitter.com/widgets.js&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">fjs</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">fjs</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}(</span><span class="nb">document</span><span class="p">,</span> <span class="s2">&#34;script&#34;</span><span class="p">,</span> <span class="s2">&#34;twitter-wjs&#34;</span><span class="p">);</span>
</span></span></code></pre></div><h2 id="quelltext-von-facebook"><a href="#quelltext-von-facebook" class="heading-anchor">Quelltext von Facebook</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">d</span><span class="p">,</span> <span class="nx">s</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">fjs</span> <span class="o">=</span> <span class="nx">d</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="nx">s</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span><span class="p">(</span><span class="nx">d</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">id</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nx">js</span> <span class="o">=</span> <span class="nx">d</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nx">js</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nx">js</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="s2">&#34;//connect.facebook.net/de_DE/all.js#xfbml=1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fjs</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">fjs</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}(</span><span class="nb">document</span><span class="p">,</span> <span class="s1">&#39;script&#39;</span><span class="p">,</span> <span class="s1">&#39;facebook-jssdk&#39;</span><span class="p">));</span>
</span></span></code></pre></div><p>Zwecks der Lesbarkeit habe ich die Funktionen entsprechend formatiert.</p>
<p>Selbst Nicht-Programmierern dürften die Ähnlichkeiten kaum entgehen. Die Variablennamen sind identisch und sogar die Art der URL-Angabe ohne Protokoll. Selbst das if-Conditional und damit die Methode das externe JavaScript nicht zweimal einzubinden, stimmen überein &ndash; nur die Schreibweise ist etwas anders.</p>
<p>Aus meiner Sicht geht dieses Vorgehen vollkommen in Ordnung. Man muss nicht ständig das Rad neu erfinden. Gerade Programmierer tun das sehr gerne, obwohl es nur selten notwendig ist.</p>
<p>Twitter und Facebook sind Technologie-Vorreiter, neben Google die zwei wichtigsten im gesamten Netz &ndash; warum sollten sie also nicht gegenseitig voneinander profitieren? Auch wenn es nur um einen Code-Schnipsel geht, der externe JavaScripts lädt.</p>
<p>Andere Firmen (Hallo, Oracle!) holen selbst bei wesentlich geringeren Quelltext-Ähnlichkeiten gleich die Klage-Keule raus. Durch die Möglichkeit in den USA Patente auf Software zu bekommen, ist sowas sogar oft von Erfolg gekrönt &hellip;</p>
<p>Ich bin kein Verfechter von Open Source, auch wenn ich es grundsätzlich für eine gute Sache halte. Noch bin ich der Meinung, dass Software ein Allgemeingut wäre und jedem kostenlos zur Verfügung stehen müsse.</p>
<p>Jedem Entwickler muss das Recht zustehen, sein Produkt zu verkaufen und es schützen zu dürfen. Im Fall von Trivial-Patenten, geht es nicht mehr darum.</p>
<p>Man will nur noch der Konkurrenz schaden und Geld rausholen, obwohl man selbst oft mehr als genug hat. Firmen werden gekauft, um an die Patente zu kommen und anschließend andere Firmen mit Klagen zu überziehen.</p>
<p>Egal, ob Apple, Samsung, Motorola (Google), Nokia oder sonst wer. Hört endlich auf damit! Keiner eurer Kunden will Import-Verbote, absurd hohe Patentabgaben für verkaufte Geräte oder sonstige Auswüchse eurer Advokaten-Armeen.</p>
<p>Aus Apples Sicht ist Android ein geklautes Produkt. Objektiv gesehen kann man dem sogar in Teilen zustimmen. Nur: na und?</p>
<p>Apple hat gute Ideen, Google hat gute Ideen. Nutzt sie, um euch gegenseitig zu verbessern und stellt diese lächerlichen Grabenkämpfe ein, die euch letztlich mehr schaden als nützen.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>PHP-Autoloader nach dem PSR-0-Standard</title>
      <link>https://webcodr.io/2012/06/php-autoloader-nach-dem-psr-0-standard/</link>
      <pubDate>Sun, 17 Jun 2012 22:20:12 +0100</pubDate>
      <guid>https://webcodr.io/2012/06/php-autoloader-nach-dem-psr-0-standard/</guid>
      <description>Wenn’s um das Schreiben eines Autoloaders in PHP geht, kochen viele Entwickler gern ihr eigenes Süppchen. Sofern nun mehrere gleichzeitig aktiv sind, kann das zu Problemen führen und ggf. sogar dafür sorgen, dass eine Alternative gesucht werden muss.
Die PHP Framework Interoperability Group (kurz FIG) hat sich dieses Problems angenommen und eine Spezifikation für Autoloader entwickelt, die Interoperabilität sicherstellt.
Der PSR-0-Standard besteht aus ein paar recht simplen Regeln, die sich sehr einfach umsetzen lassen und z.T. sicher schon von vielen genutzt wurden:
</description>
      <content:encoded><![CDATA[<p>Wenn&rsquo;s um das Schreiben eines Autoloaders in PHP geht, kochen viele Entwickler gern ihr eigenes Süppchen. Sofern nun mehrere gleichzeitig aktiv sind, kann das zu Problemen führen und ggf. sogar dafür sorgen, dass eine Alternative gesucht werden muss.</p>
<p>Die <a href="https://github.com/php-fig/fig-standards">PHP Framework Interoperability Group</a> (kurz FIG) hat sich dieses Problems angenommen und eine Spezifikation für Autoloader entwickelt, die Interoperabilität sicherstellt.</p>
<p>Der <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md">PSR-0-Standard</a> besteht aus ein paar recht simplen Regeln, die sich sehr einfach umsetzen lassen und z.T. sicher schon von vielen genutzt wurden:</p>
<ul>
<li>Ein qualifizierter Namespace hat folgende Struktur <code>\&lt;Vendor Name&gt;\(&lt;Namespace&gt;\)*&lt;Class Name&gt;</code></li>
<li>Jeder Namespace hat einen Haupt-Namespace (Vendor Name)</li>
<li>Jeder Namespace kann beliebig viele Unter-Namespaces besitzen</li>
<li>Jeder Namespace-Separator wird in einen <code>DIRECTORY_SEPARATOR</code> konvertiert, wenn aus dem Dateisystem geladen wird</li>
<li>Das Zeichen &ldquo;_&rdquo; (Underscore) wird in einen <code>DIRECTORY_SEPARATOR</code> konvertiert und hat keine spezielle Bedeutung.</li>
<li>Der qualifizierte Namespace inkl. Klasse bekommt die Endung &ldquo;.php&rdquo; angehängt, um die Datei zu laden.</li>
<li>Namespaces, Vendor Names und Klassennamen dürfen alphabetische Zeichen in jeder Kombination aus Groß- und Kleinschreibung enthalten.</li>
</ul>
<h2 id="beispiel-implementation"><a href="#beispiel-implementation" class="heading-anchor">Beispiel-Implementation</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">namespace</span> <span class="nx">WebCodr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Loader</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="nf">registerAutoloader</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nx">spl_autoload_register</span><span class="p">(</span><span class="k">array</span> <span class="p">(</span><span class="s1">&#39;WebCodr\\Loader&#39;</span><span class="p">,</span> <span class="s1">&#39;load&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="nf">load</span><span class="p">(</span><span class="nv">$class</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="nx">substr</span><span class="p">(</span><span class="nv">$class</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">)</span> <span class="o">!==</span> <span class="s1">&#39;WebCodr&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nv">$libraryRoot</span> <span class="o">=</span> <span class="nx">realpath</span><span class="p">(</span><span class="no">__DIR__</span> <span class="o">.</span> <span class="s1">&#39;/../&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$classFileName</span> <span class="o">=</span> <span class="nx">str_replace</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;\\&#39;</span><span class="p">,</span> <span class="s1">&#39;_&#39;</span><span class="p">),</span> <span class="nx">DIRECTORY_SEPARATOR</span><span class="p">,</span> <span class="nv">$class</span><span class="p">)</span> <span class="o">.</span> <span class="s1">&#39;.php&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$fileName</span> <span class="o">=</span> <span class="nx">realpath</span><span class="p">(</span><span class="nv">$libraryRoot</span> <span class="o">.</span> <span class="nx">DIRECTORY_SEPARATOR</span> <span class="o">.</span> <span class="nv">$classFileName</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="nx">is_readable</span><span class="p">(</span><span class="nv">$fileName</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">include_once</span><span class="p">(</span><span class="nv">$fileName</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Die Klasse stellt zwei statische Methoden bereit. Mit <code>Loader::registerAutoloader()</code> wird die Methode <code>Loader::load()</code> als SPL-Autoloader registriert.</p>
<p><code>Loader::load()</code> prüft zuerst, ob sich die angeforderte Klasse überhaupt im Namespace WebCodr befindet. Falls dies nicht der Fall ist, wird durch den leeren Rückgabewert signalisiert, dass die Klasse mit diesem Autoloader nicht geladen werden kann und die SPL geht zum nächsten registrierten Autoloader über.</p>
<p>Anschließend wird der Pfad zur Klasse zusammengesetzt und die Datei mittels <code>include_once()</code> eingebunden. Optional könnte man im Fehlerfall natürlich noch eine Exception werfen.</p>
<h2 id="aufruf-des-autoloaders"><a href="#aufruf-des-autoloaders" class="heading-anchor">Aufruf des Autoloaders</a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">include_once</span><span class="p">(</span><span class="s1">&#39;Loader.php&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">\WebCodr\Loader</span><span class="o">::</span><span class="na">registerAutoloader</span><span class="p">();</span>
</span></span></code></pre></div><h2 id="fazit"><a href="#fazit" class="heading-anchor">Fazit</a></h2>
<p>PSR-0 ist schnell und einfach implementiert. Für neue Projekte gibt es also keinen Grund, sich nicht daran zu halten. In bestehendem Code könnte es recht aufwendig sein, den Standard umzusetzen &ndash; je nachdem, welche Benamungsschemata und Verzeichnisstrukturen bereits verwendet werden.</p>
<p>Man sollte den Aufwand aber nicht scheuen. Was bringt einem schon die tollste Library oder ein cooles Framework, wenn es aufgrund eines schlecht implementierten Autoloaders, kaum eingesetzt werden kann?</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>IHK != agile</title>
      <link>https://webcodr.io/2012/04/ihk-agile/</link>
      <pubDate>Sat, 28 Apr 2012 22:19:16 +0100</pubDate>
      <guid>https://webcodr.io/2012/04/ihk-agile/</guid>
      <description>Während der Berufsschule wird einem klassisches Projekt-Management eingetrichtert und immer wieder betont, wie wichtig das doch wäre. Dabei wird natürlich nach dem Wasserfallmodell vorgegangen, Gantt-Diagramme gezeichnet (wer braucht bei einer IT-Ausbildung schon Rechner?), mit Netzplänen die Dauer einzelner Schritte in Tagen ausgerechnet (von Hand wohlgemerkt, dementsprechend falsch sind die dann auch meistens) oder die Schüler auf andere Weise mit Dingen malträtiert werden, die zunehmend für die Software-Branche als unbrauchbar betrachtet werden.
</description>
      <content:encoded><![CDATA[<p>Während der Berufsschule wird einem klassisches Projekt-Management eingetrichtert und immer wieder betont, wie wichtig das doch wäre. Dabei wird natürlich nach dem <a href="http://de.wikipedia.org/wiki/Wasserfallmodell">Wasserfallmodell</a> vorgegangen, Gantt-Diagramme gezeichnet (wer braucht bei einer IT-Ausbildung schon Rechner?), mit Netzplänen die Dauer einzelner Schritte in Tagen ausgerechnet (von Hand wohlgemerkt, dementsprechend falsch sind die dann auch meistens) oder die Schüler auf andere Weise mit Dingen malträtiert werden, die zunehmend für die Software-Branche als unbrauchbar betrachtet werden.</p>
<p>Bei Software-Projekten nach dem Wasserfallmodell vorzugehen, hat sich immer wieder als nicht praktikabel herausgestellt. Für Bau-Ingenieure, bei denen sich alles vorher planen und ausrechnen lässt, mag das wunderbar funktionieren.</p>
<p>In der Software-Entwicklung lässt sich aber nun mal nichts vollständig planen. Schon gar nicht zeitliche Angaben, wie sie die IHK für das Projekt auf eine halbe Stunde genau will.</p>
<p>Unvorhergesehene Dinge treten immer auf. Dabei können ganze Lösungsansätze vollkommen eliminiert werden und die Arbeit von Tagen, manchmal sogar Wochen war vergebens.</p>
<p>Oft verursachen selbst kleine Fehler große Verzögerungen. Darum versagen klassische Modelle. In solchen Situationen sind sie zu starr und erlauben keine angemessene Reaktion, um das Problem schnell anzugehen. Seit mittlerweile 20 Jahren werden Alternativen entwickelt bzw. setzen sich zunehmend durch.</p>
<h2 id="agil-arbeiten"><a href="#agil-arbeiten" class="heading-anchor">Agil arbeiten</a></h2>
<p>Als Software-Projekte immer größer bzw. komplexer wurden und damit auch die Probleme durch klassisches Projektmanagement, entstanden die Überlegungen zu <a href="http://de.wikipedia.org/wiki/Agile_Softwareentwicklung">agilen Entwicklungsmethoden</a>. Sie sind deutlich flexibler und leichtgewichtiger als klassische Prozesse und widmen sich auch den sozialen Aspekten der Software-Entwicklung.</p>
<p>An dieser Stelle tiefer in das Thema einzusteigen, würde den Rahmen deutlich sprengen, daher verweise ich auf die Blogs meiner Kollegen <a href="http://www.agileblog.org/">Dominik Jungowski</a> und <a href="http://proessler.wordpress.com/">Peter Roessler</a> sowie <a href="http://www.agile42.com/en/blog/">Agile42</a>.</p>
<p>Auch wenn ich erst seit dem Wechsel zu <a href="http://www.chip.de/">Chip Online</a> mit agiler Entwicklung in Berührung gekommen bin, möchte ich nicht mehr darauf verzichten.</p>
<p>Ich durfte vorher oft genug erleben, wie herkömmliche Methoden versagt haben und mir als Programmierer nur Steine in den Weg legten, während agile Methoden Spaß machen und darauf ausgelegt sind, dass ich meine Arbeit angenehmer und besser erledigen kann.</p>
<p>Genau darum verstehe ich auch nicht, warum während der Ausbildung Dinge gelehrt werden, die in jeder größeren Software-Schmiede längst abgeschafft wurden.</p>
<p>Zumal es auch öfter der Fall sein dürfte, dass Auszubildende eigentlich agil in ihrem Betrieb arbeiten, aber in der Berufsschule mit klassischem Projektmanagement konfrontiert werden.</p>
<p>Man sollte noch darauf im Lehrplan eingehen, aber als Negativbeispiel um die Vorteile agiler Entwicklung aufzuzeigen.</p>
<p>Ich wage sogar zu behaupten, dass ein Auszubildender aus unserem hausinternen Workshop zu agilen Methoden innerhalb eines Tages mehr mitnehmen kann, als nach den 60 Tagen Berufsschule des ersten Jahres, in denen Projektmanagement, Wasserfallmodell &amp; Co über sie herfallen.</p>
<p>Übrigens: auch den Lehrern könnte etwas mehr Agilität nicht schaden. Es ließen sich ganz andere Wege beschreiten, die Spaß machen und den Schülern Wissen viel effektiver bzw. dauerhaft vermitteln können &hellip; aber das ist ein anderes Thema, auf das ich evtl. in einem weiteren Eintrag genauer eingehen werde.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
