<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: hong</title>
    <description>The latest articles on Forem by hong (@cocoroutine).</description>
    <link>https://forem.com/cocoroutine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F126768%2Fdab45ec5-61d0-426c-be7e-631d98ea9c5d.png</url>
      <title>Forem: hong</title>
      <link>https://forem.com/cocoroutine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cocoroutine"/>
    <language>en</language>
    <item>
      <title>OOP + S = OOPS</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Sat, 01 Jun 2019 01:37:45 +0000</pubDate>
      <link>https://forem.com/cocoroutine/oop-s-oops-39cc</link>
      <guid>https://forem.com/cocoroutine/oop-s-oops-39cc</guid>
      <description>&lt;h2&gt;
  
  
  OOP
&lt;/h2&gt;

&lt;p&gt;When we first started with OOP it was about modelling objects after things. A more modern approach says that OOP is about the messages passed between these objects. But the more I draw message diagrams, the more I realize OOP is like a hidden object game. You are always discovering new objects that can be brought to life.&lt;/p&gt;

&lt;h3&gt;
  
  
  OOP Opponents
&lt;/h3&gt;

&lt;p&gt;Some OOP haters, like Brian Will from Youtube, say that OOP makes you model objects that do not exist in real life. These are your 'Managers', 'Builders' and 'Coordinators". Yes these don't make sense in the real world, but what is the alternative? Long lines of confusing code? Documentation embedded into your code that lies? A spiders mess of modules with complicated api?&lt;/p&gt;

&lt;p&gt;The only other viable solution to OOP is purely functional programming, but this comes with it's own set of issues.&lt;/p&gt;

&lt;p&gt;I'll admit when I goto describe the big picture (class hierarchy), it can get blurry.  The global scope is messy.  However when I look at individual objects, the code is clear with little documentation needed. The local scope is clean. This is where UML diagrams for the big picture can help.&lt;/p&gt;

&lt;h2&gt;
  
  
  The S in SOLID
&lt;/h2&gt;

&lt;p&gt;The S stands for Single Responsibility. A method, class or module should only be responsible for one thing.  A method, class or module should only have one reason to change. So why is it so hard to implement?&lt;/p&gt;

&lt;h3&gt;
  
  
  S means Struggle
&lt;/h3&gt;

&lt;p&gt;It's not just you. The single responsibility rule is completely arbitrary.  It changes with the problem space.  Newbies and seasoned coders alike still have problems. It get's easier with experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  S means Spiral
&lt;/h3&gt;

&lt;p&gt;If you follow the rule strictly, you might end up with classes with just one function. Then you will have too many objects with messy messaging between them.  How do you know what should be another object and what should not?&lt;/p&gt;

&lt;p&gt;It's not one answer fits all. I would say lean towards having more objects than less. Unless you can safely answer that this objects requirements will not change. If you find an object to be useless, you can always merge functionality.&lt;/p&gt;

&lt;p&gt;However the opposite is not always true and may cause a spiral of changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  S means Simple rule
&lt;/h3&gt;

&lt;p&gt;Sandi Metz of POODR came up with a simple rule. Methods should be at most 4 lines long and classes should be at most 100. This is using the standard 80 character width. Try it out.&lt;/p&gt;

&lt;p&gt;4 lines might seem too restrictive, but it's actually a lot.  If you are having trouble, then you can split up your methods. If it's still too long, a hidden object might be waiting to be discovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  OOP really means
&lt;/h2&gt;

&lt;p&gt;OOP is about protecting your code against changing product requirements.  The smaller your objects are the better you can defend. Adhering to the single responsibility rule helps with this.&lt;/p&gt;

&lt;p&gt;OOP is about the 80/20 rule. 80% of the benefit should come from 20% effort.  OOP can achieve this.&lt;/p&gt;

&lt;h2&gt;
  
  
  clean code
&lt;/h2&gt;

&lt;p&gt;Writing clean code is not easy. I'm still refactoring my code and so should you. Go on a treasure hunt and find those hidden objects!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>oop</category>
      <category>solid</category>
    </item>
    <item>
      <title>In defense of Test Driven Development</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Mon, 08 Apr 2019 19:31:17 +0000</pubDate>
      <link>https://forem.com/cocoroutine/in-defense-of-test-driven-development-4h0e</link>
      <guid>https://forem.com/cocoroutine/in-defense-of-test-driven-development-4h0e</guid>
      <description>&lt;h2&gt;
  
  
  In defense of Test Driven Development
&lt;/h2&gt;

&lt;p&gt;I'm still learning to write great code like everyone else. Recently there's been some articles bashing TDD. I would like to share what worked for me with TDD.&lt;/p&gt;

&lt;h3&gt;
  
  
  OOP and TDD a good pair
&lt;/h3&gt;

&lt;p&gt;Good OOP should follow SOLID and clean code principles. Classes should be small and methods even smaller. This makes writing unit tests much easier as there is much less to test per test case.&lt;/p&gt;

&lt;p&gt;Clean code by Uncle Bob and POODR by Sandi Metz both dedicate large chapters to testing. This is not by accident. Test driven development is a huge part of writing maintainable code.  If you are having problems with test driven development, perhaps your classes and methods are too long. Consider whether or not your code follows SOLID and clean code principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test cases first
&lt;/h3&gt;

&lt;p&gt;Before TDD, what I did was create a class and define the attributes and methods that I think I would need. I found this habit hard to break, until I forced myself to create test cases before I even wrote one line of code. How I did this was to create easier unit tests.&lt;/p&gt;

&lt;p&gt;Python example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_myobject:

    #check if the attribute exists
    self.assertTrue(hasattr(myobject, 'myattribute'))

    #check the type
    self.assertIsInstance(myobject.mylist, list)

    #check if function
    self.assertTrue(callable(myobject.mymethod)

    #check if attribute defaults to False
    self.assertFalse(myobject.my_false_attribute)

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



&lt;p&gt;This is very similar to creating the basic structure of a class without writing the actual class. Some would argue that these unit tests do not test anything and are not worth it. After all why would you test basic language concepts like variable assignment?&lt;/p&gt;

&lt;p&gt;I would say an object's public API is a contract and should be tested. Any change of these attributes will break code. This would be an easy fix, but also these unit tests are easy to write. This make it almost free.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips
&lt;/h3&gt;

&lt;p&gt;Have your class and unit tests side by side when writing and updating code. If you update one, update the other.&lt;/p&gt;

&lt;p&gt;If your constructors contain any conditional assignment logic, then you should definitely write unit tests for this.&lt;/p&gt;

&lt;p&gt;I only write unit tests for methods that are public. If your private methods contain some tricky logic that needs to be tested, perhaps consider creating a mixin class for that method and exposing it publicly.&lt;/p&gt;

&lt;p&gt;If your test cases import a bunch of other classes, that can show you are testing a too much. Practice DRY (Don't repeat yourself) in testing code as well.  Use mocks and stubs in replace of other objects that your unit tests depend on instead of importing other objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;Good test cases have made my flow much better.  Now I can rapidly design and add new features and they mostly work on first run. If I do have errors, the issue is with integration and not the single object itself.  Refactoring is also easier as I know when I break stuff.  &lt;/p&gt;

&lt;p&gt;This is what worked for me. Good luck on your journey and help others along the way!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>testing</category>
      <category>unittesting</category>
      <category>python</category>
    </item>
    <item>
      <title>The skinny on Python dev environment and packaging (pip)</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Thu, 14 Mar 2019 18:48:01 +0000</pubDate>
      <link>https://forem.com/cocoroutine/the-skinny-on-python-dev-environment-and-packaging-pip-74b</link>
      <guid>https://forem.com/cocoroutine/the-skinny-on-python-dev-environment-and-packaging-pip-74b</guid>
      <description>&lt;p&gt;Welcome to the wild world of Python dev. Where nothing is consistent and there is no such thing as as consensus.&lt;/p&gt;

&lt;p&gt;Don't worry I'll be your guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I quietly released &lt;a href="http://github.com/cocoroutine/pyquilted"&gt;pyquilted&lt;/a&gt; which generates nice looking resumes from Yaml in PDF. I learned a lot about setting up a python dev environment and packaging an app to distribute on Pypi (pip) and now I am sharing that knowledge.&lt;/p&gt;

&lt;p&gt;You can find out more about quilted resumes &lt;a href="http://github.com/cocoroutine/quilted"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unittests
&lt;/h2&gt;

&lt;p&gt;Running test cases were for some reason harder than it should be. Follow these steps to make your life easier.&lt;/p&gt;

&lt;p&gt;Create a directory called 'test' in your project root.&lt;/p&gt;

&lt;p&gt;Name all your tests 'test_*'.&lt;/p&gt;

&lt;p&gt;Put an __init__.py so that the directory get's recognized as a package.&lt;/p&gt;

&lt;p&gt;running all tests on Python 2 and 3&lt;br&gt;
&lt;code&gt;python -m unittest discover&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running one test&lt;br&gt;
&lt;code&gt;python -m unittest test.test_name&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Venv vs VirtualEnv vs PipEnv
&lt;/h2&gt;

&lt;p&gt;These are all ways to isolate your python pip environment so you do not pollute your main system python. Uninstalling a package and it's dependecies is a pain in pip.  This avoids this by allowing you to easily delete and create new envs.&lt;/p&gt;
&lt;h4&gt;
  
  
  But which one do you go with?
&lt;/h4&gt;

&lt;p&gt;Venv &lt;del&gt;vs VirtualEnv vs PipEnv&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;Just go with venv. It comes standard with python and is officially recommended post 3.3+.  It also has less gotchas than virtualenv and I don't want to be gotten.&lt;/p&gt;

&lt;p&gt;to create a new venv folder&lt;br&gt;
&lt;code&gt;python -m venv venv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;to load the environment&lt;br&gt;
&lt;code&gt;source venv/bin/activate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;turn off the venv&lt;br&gt;
&lt;code&gt;deactivate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pipvenv is nice, but it's not standard and is based on virtualenv.&lt;/p&gt;
&lt;h4&gt;
  
  
  Python 2.7 and Venv
&lt;/h4&gt;

&lt;p&gt;Venv doesn't support python 2.7, bummer.&lt;/p&gt;

&lt;p&gt;Simple solution&lt;br&gt;
&lt;code&gt;pip install py2venv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This installs virutalenv for you and creates a wrapper around virtualenv. Meaning you can use the venv command. Great!&lt;/p&gt;
&lt;h4&gt;
  
  
  Where to put your venv folder?
&lt;/h4&gt;

&lt;p&gt;If you are just running one venv per project, put it in the same directory as the project root and name the folder 'venv'. Make sure in your .gitignore you have added 'venv'—on github and gitlab this is added for you.&lt;/p&gt;

&lt;p&gt;one venv environment per project&lt;br&gt;
&lt;code&gt;project_root/venv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The issues comes when you want different venv environments for different python versions you are testing. Here's a few options&lt;/p&gt;

&lt;p&gt;multiple venv per project&lt;br&gt;
&lt;code&gt;project_root/venv/{{python_version}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;alternative, venv in home folder&lt;br&gt;
&lt;code&gt;~/venv/{{project_name}}_{{python_version}}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  setup.py
&lt;/h2&gt;

&lt;p&gt;Setup.py is like a makefile for your app. It's based off of setuptools. It normally comes pre-installed. If not you can install it like so&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install setuptools&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The documentation can be found &lt;a href="https://setuptools.readthedocs.io/en/latest/"&gt;here&lt;/a&gt;. Some parts are either confusing or not working as expected. I noted the parts here.&lt;/p&gt;

&lt;p&gt;You can see an example of my setup.py in the pyquilted &lt;a href="https://github.com/cocoroutine/pyquilted"&gt;source&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Command line entry point
&lt;/h4&gt;

&lt;p&gt;You want to run your app in the terminal using your app's sweet name. This was a lot tricker than it should be. After endless searching, this method below worked for me.&lt;/p&gt;

&lt;p&gt;In your project root, create a file named main.py. Have one function named main that calls your run function. An example &lt;a href="https://github.com/cocoroutine/pyquilted/blob/master/pyquilted/main.py"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Add the following into your setup.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entry_points={
    'console_scripts': ['command=pacakge.main:main']
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where 'command' is the command you want to use. 'package' is your package name.&lt;/p&gt;

&lt;p&gt;For example my pyquilted entry point&lt;br&gt;
&lt;code&gt;'console_scripts': ['pyquilted=pyquilted.main:main']&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Markdown readme
&lt;/h4&gt;

&lt;p&gt;Pypi now supports markdown. Use a with open file handler to set your readme doc to a variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;long_description=readme,
long_description_content_type='text/markdown'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Including non py files
&lt;/h4&gt;

&lt;p&gt;There are two ways to add files to either your site_packages for data or your source package for test cases and such.&lt;/p&gt;

&lt;h4&gt;
  
  
  package data
&lt;/h4&gt;

&lt;p&gt;Use the below format for adding data files to your site_packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package_data={
    'package_name': ['directory/*.pattern']
},
include_package_data=True

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



&lt;h4&gt;
  
  
  MANIFEST.in
&lt;/h4&gt;

&lt;p&gt;This includes files in your source pacakge that are not in your site_packages folder. The format is a little weird.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include file   # include single file
recursive-include directory pattern # include a directory and files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  requirements.txt
&lt;/h2&gt;

&lt;p&gt;Skip it. It's not really necessary, but simple to make.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Pyenv
&lt;/h2&gt;

&lt;p&gt;Still crying over the disaster that was migrating from Python 2 to 3. Me too, join the club. We stil have to support Python 2 and test other versions of 3 as well. How to solve multiple python versions? We could learn Vagrant or Docker.  Nah that's way overkill.&lt;/p&gt;

&lt;p&gt;Solution Pyenv.&lt;/p&gt;

&lt;p&gt;Install Pyenv by following instructions here &lt;a href="https://github.com/pyenv/pyenv"&gt;pyenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;list installable python versions&lt;br&gt;
&lt;code&gt;pyenv install --list&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;install version&lt;br&gt;
&lt;code&gt;pyenv install 2.7.15&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;list versions installed&lt;br&gt;
&lt;code&gt;pyenv versions&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;switch to python version&lt;br&gt;
&lt;code&gt;pyenv global 2.7.15&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Debian, Ubuntu and others
&lt;/h4&gt;

&lt;p&gt;On Debian, Ubuntu and other distros, you will get an error about ssl when trying to build older versions of python. The issue is that libssl 1.1 is not compatble with Python &amp;lt; 3.3. The solution is to download the dev headers for libssl 1.0 and link them manually when running pyenv install, per this &lt;a href="https://github.com/pyenv/pyenv/issues/945#issuecomment-409627448"&gt;thread&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CFLAGS="-I/path_to/libssl1.0-dev/include -I/path_to/libssl1.0-dev/include/x86_64-linux-gnu" \
LDFLAGS="-L/path_to/libssl1.0-dev/lib/x86_64-linux-gnu" pyenv install 2.7.15
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Eggs everywhere
&lt;/h2&gt;

&lt;p&gt;To stop python from creating eggs that you accidently upload to Pypi when you are testing.&lt;/p&gt;

&lt;p&gt;Use the below command&lt;br&gt;
&lt;code&gt;pip install .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;instead of this command&lt;br&gt;
&lt;code&gt;python setup.py install&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building and Wheels
&lt;/h2&gt;

&lt;p&gt;Honestly wheel files are not necessary. The difference in install time between source and binary is like a few seconds. However it's really easy to build binary wheels so why not.&lt;/p&gt;

&lt;p&gt;make sure you have wheel installed&lt;br&gt;
&lt;code&gt;pip install wheel&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;run this to build your packages&lt;br&gt;
&lt;code&gt;python setup.py sdist bdist_wheel&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally upload to Pypi
&lt;/h2&gt;

&lt;p&gt;Create an account on Pypi.org. Then install twine which is the official pypi app&lt;br&gt;
&lt;code&gt;pip install twine&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Upload with this command&lt;br&gt;
&lt;code&gt;twine upload --skip-existing dist/*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The key is skip existing files, otherwise you get errors when uploading the dist folder with existing files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Congrats!
&lt;/h2&gt;

&lt;p&gt;Congrats you beat the final boss! Pat yourself on the back for finally deciphering python dev environment.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>quicktip</category>
      <category>resources</category>
    </item>
    <item>
      <title>Truth about Template Engines Part 2</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Wed, 13 Feb 2019 19:49:52 +0000</pubDate>
      <link>https://forem.com/cocoroutine/truth-about-template-engines-part-2-nf6</link>
      <guid>https://forem.com/cocoroutine/truth-about-template-engines-part-2-nf6</guid>
      <description>&lt;h2&gt;
  
  
  My background
&lt;/h2&gt;

&lt;p&gt;This is part 2 of my articles on template engines. Specifically today I am writing about the Mustache spec.&lt;/p&gt;

&lt;p&gt;What qualifies me to pass judgement on templating engines? I have written web and email templates for fortune 500 companies. Some of which have been large gnarly order confirmations and airline reservations full of beautiful, un-readable business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Mustache
&lt;/h2&gt;

&lt;p&gt;When logic-less Mustache came onto the scene. It did something amazing; which was to get other programmer's to embrace it and re-write it in their language of choice. Sandi Metz writer of POODR said that "if your design is good then others would want to copy it". I think this applies.  Mustache was really onto something and logic-less really made sense.&lt;/p&gt;

&lt;p&gt;Except Mustache is not logic-less. It contains conditional and looping logic. I would say it's a minimal logic templating language. You can also become full logic by embedding lambdas into your data is too. If you are thinking adding callable functions to your json data sounds like a bad idea, it is.&lt;/p&gt;

&lt;p&gt;Mustache is not perfect. In fact if it were, it would be the most downloaded library for JavaScript templating. It's not, Handlebars is. Proving that logic is still king.&lt;/p&gt;

&lt;p&gt;In the following, I will outline some parts of the spec that I think need some work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in a symbol?
&lt;/h2&gt;

&lt;p&gt;A quick rundown of Mustache's symbols and their definitions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;symbol&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{{ }}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;delimiters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#&lt;/td&gt;
&lt;td&gt;begin section&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;td&gt;end section&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;inverted sections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;gt;&lt;/td&gt;
&lt;td&gt;partials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;&lt;/td&gt;
&lt;td&gt;unescape, safe-content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;comment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;current node operator?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;&lt;/td&gt;
&lt;td&gt;proposed layout operator&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just in real life sometimes choosing the right words can go a long way. It's clear that the choices for symbols and their meaning were JavaScript influenced. However compared to other languages it may cause some confusion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'#' in many scripting languages is a comment&lt;/li&gt;
&lt;li&gt;'!' is negation in many languages&lt;/li&gt;
&lt;li&gt;'.' it's not mentioned in the spec, but refers to the current variable?&lt;/li&gt;
&lt;li&gt;'&amp;gt;' vs '&amp;lt;' partial vs layout will be confusing if implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are these symbols any better than having the actual word? To any non-programmer at first glance these symbols make reading templates worse. Compare to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{{if section }}

{{not section }}

{{each item }}

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



&lt;h2&gt;
  
  
  Truthy or Falsey
&lt;/h2&gt;

&lt;p&gt;One of the tenants of Mustache is that it aims to be language agnostic. This is at a cost of clarity between language implementations.&lt;/p&gt;

&lt;p&gt;The below Mustache template will render differently depending on which language it's rendered on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Template:

Shown.
{{#person}}
  Never shown!
{{/person}}


Hash:

{
    "person": false  // or '', 0, "0", [], {}
}

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



&lt;p&gt;Below is a brief table of some of the different Truthy evaluations in scripting languages.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;lang&lt;/th&gt;
&lt;th&gt;''&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;"0"&lt;/th&gt;
&lt;th&gt;{}&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Php&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This variability in the spec is in my opinion one of it's weaknesses. From a business perspective, it doesn't make any sense why this exists other than to make it easier for developers to implement the spec. Templating engine developers should not be the target audience for a template language.&lt;/p&gt;

&lt;p&gt;I know that others have voiced their opinions on this matter and the community seems divided. However consider this conversation. "If we migrate to a new backend, our clients might see bugs in their templates because of the way Mustache is designed". Try selling that to your managers.&lt;/p&gt;

&lt;p&gt;This might seem like a non-issue, as you are not likely to transfer your templates between languages. However when you are choosing a templating engine to be used by non-programmers, stuff like this can bite you. Also backend re-writes do happen.&lt;/p&gt;

&lt;p&gt;Almost any standardization would be better than no standardization at all. It's just the idea that tying evaluation of of a template block to a language's own internal truth table makes no sense. After all it could be the case that I want to show that 0 items are available.&lt;/p&gt;

&lt;p&gt;In my professional experience, it's almost always safer to be explicit when rendering a conditional block. There is no equivalent problem in other templating languages because you can always just do an '==' comparison. This is explicit.&lt;/p&gt;

&lt;p&gt;The problem arises because Mustache aims to be logic-less which is a mismatch for some template blocks use cases. Going with Python's model of everything Falsey is good enough. Just please not PHP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Whitespace
&lt;/h2&gt;

&lt;p&gt;Whitespace is sacred. One of my biggest pet peeves with templating languages is that they always clobber whitespace. Whitespace is ambiguous. The Mustache spec is also loose with regards to whitespace. Consider the below Mustache code:&lt;/p&gt;

&lt;p&gt;Is this a variable or section?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{ #person }}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Some developers have solved this ambiguity by requiring that mustaches be continuous e.g. &lt;code&gt;{{#person}}&lt;/code&gt;. However consider the below:&lt;/p&gt;

&lt;p&gt;What's easier to read?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{name}} vs {{ name }}

{{#person}} vs {{# person }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a perfect world, whitespace in general should be preserved. This is difficulty to implement as whitespace is ambiguous by nature.&lt;/p&gt;

&lt;p&gt;Should this &lt;code&gt;{{variable}}&lt;/code&gt; preserve spacing if it is null? Is it one or two spaces?&lt;/p&gt;

&lt;p&gt;How about pre, post and nested newlines in a null section? Indents too? It gets complex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         {{#mysection}}
              {{nested}}
         {{/mysection}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The spec is unclear on all these scenarios. Some implementations have restricted spacing while others have not. It is the same with preserving whitespacing. This result is too much variability in implementations. This could be cleared up with a more clear spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template Inheritance
&lt;/h2&gt;

&lt;p&gt;One of the most requested features is template inheritance. This is when you have a base layout that other templates can inherit. For example a layout with a header and footer and other templates can then render the body content; optionally they can override parts of the parent layout.&lt;/p&gt;

&lt;p&gt;My answer to this is No. Just No. This is a nice to have and perhaps should be an optional spec. However Mustache does not need this. I don't think this flows to with the concept of logic-less. Partials are already good enough. They are themselves a bit too much logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wishlist for Mustache 2.0
&lt;/h2&gt;

&lt;p&gt;What's better than logic-less? More logic-less! My wishlist for Mustache 2.0 involves implementing NO new features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remove lambdas feature&lt;/li&gt;
&lt;li&gt;remove set delimter feature&lt;/li&gt;
&lt;li&gt;standardize truthiness&lt;/li&gt;
&lt;li&gt;standardize whitespace rules&lt;/li&gt;
&lt;li&gt;No template inheritance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mustache 2.0 done and done&lt;/p&gt;

&lt;p&gt;Don't get me a wrong. I'm a huge fan of mustache. However like writing code, we can refactor to make it better.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>templates</category>
      <category>javascript</category>
      <category>mustache</category>
    </item>
    <item>
      <title>Firefox vs Chrome, MD two space vs GFM line breaks</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Wed, 16 Jan 2019 14:27:06 +0000</pubDate>
      <link>https://forem.com/cocoroutine/firefox-vs-chrome-md-two-space-vs-gfm-line-breaks-o22</link>
      <guid>https://forem.com/cocoroutine/firefox-vs-chrome-md-two-space-vs-gfm-line-breaks-o22</guid>
      <description>&lt;p&gt;Hi guys,&lt;/p&gt;

&lt;p&gt;I submitted my first post yesterday. My markdown that I pasted in had line breaks because it makes it easier to adhere to the 80 char rule while looking nice in editor(vim). I use traditional 2 space rule for line breaks.&lt;/p&gt;

&lt;p&gt;I submitted my post and it looked fine on Chrome and ugly in Firefox. The content had extra line breaks everywhere in FF. It looks like Firefox supports GFM style linebreaks while Chrome does not? Is that for real or am I missing something?&lt;/p&gt;

&lt;p&gt;Thanks,&lt;/p&gt;

</description>
      <category>meta</category>
    </item>
    <item>
      <title>Truth About Template Engines</title>
      <dc:creator>hong</dc:creator>
      <pubDate>Tue, 15 Jan 2019 16:42:33 +0000</pubDate>
      <link>https://forem.com/cocoroutine/truth-about-template-engines-3a7</link>
      <guid>https://forem.com/cocoroutine/truth-about-template-engines-3a7</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;I'm writing about content template engines today like Shopify's liquid,&lt;br&gt;
Python's Jinja, Mustache and the others. I am here to finally answer these&lt;br&gt;
burning questions I'm sure you all have.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's better Logic-less vs Logic-full?&lt;/li&gt;
&lt;li&gt;Why are there so many?&lt;/li&gt;
&lt;li&gt;How to choose one?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What qualifies me to pass judgement on templating engines? I have written web and email templates for some of the biggest fortune 500 companies. Some of which have been large gnarly order confirmations and airline reservations full of glorious, unreadable business logic.&lt;/p&gt;

&lt;p&gt;This is part 1 of a 2 part series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's define logic
&lt;/h3&gt;

&lt;p&gt;Logic-less templates became popular with the arrival of Mustache. Except&lt;br&gt;
Mustache is not really logic-less. There's control flow, looping and even&lt;br&gt;
custom code via lambdas. If you use Mustache without lambdas, I would consider this as close to logic-less as you can get while still being useful.&lt;/p&gt;

&lt;p&gt;Full logic in my opinion is when you are freely able to mix both content and&lt;br&gt;
any arbitrary code into your templates. Examples of such are ERB, XSLT and&lt;br&gt;
Underscore.&lt;/p&gt;

&lt;p&gt;Some where in-between are semi-logic templates. Logic can be introduced via pre-defined filters and/or custom filters. Semi-logic templates, if abused, can lead to full logic templates. This category includes Liquid, Jinja2, Handlebars, Nunjucks and many others.&lt;/p&gt;

&lt;p&gt;'View as an app' frameworks like React and Vue, I would consider to be full logic templating engines plus everything including the kitchen sink.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logic-less vs Full Logic
&lt;/h3&gt;

&lt;p&gt;In a perfect world your data lines up exactly how you want it to look in your presentation layer. You never need to write any business logic in your templates. This is where logic-less templates is a perfect match and what everyone should strive for.&lt;/p&gt;

&lt;p&gt;These style templates are very easy to read. Anyone can understand and write these. Contrast this with full logic that are hard to read and hard to write.&lt;/p&gt;

&lt;p&gt;So why use full logic? There are advantages to full logic templates. They are extremely flexible and you can hack quick fixes when you don't want to write complicated controller logic. I've written some crazy business logic into templates because there are always those clients whose requirements are never sane.&lt;/p&gt;

&lt;p&gt;In my experience with working with many clients, the data almost never lines up with the presentation requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know your audience
&lt;/h3&gt;

&lt;p&gt;Not everyone is a programmer. From my experience, anyone trying to teach anything beyond simple control structures to a large group of non-programmers, is going to have a bad time. Having your template engine be simpler gives it access to a broader range of technical expertise.&lt;/p&gt;

&lt;p&gt;Imagine if Shopify had used ERB. This would have been a headache to train all customers and have random scripts to solve for business logic. Template writers are not backend coders. This would have also have been a big risk given anyone access to freely execute ruby code through templates.&lt;/p&gt;

&lt;p&gt;Even for large teams of experienced programmers, I would still say it's an anti-pattern to use a full logic templating engine. Full logic just leads to HTML content mixed with ugly code. The logic embedded in the code will be hard to test and will introduce bugs.&lt;/p&gt;

&lt;p&gt;I wrote XSLT in a large team of experienced technologists. XSLT is in itself a verbose and complex language for templates. Simple changes were fine, but anything greater required hours to write and test. Yet we still did it, largely to solve for gaps in our product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it ever okay to go full logic?
&lt;/h3&gt;

&lt;p&gt;Yes, I would say under certain circumstances, it's okay to use full logic templates. If your team is small and experienced developers you will be fine. However if you find yourself leaning on it too much, it could mean there are some problems with your design. You will start building technical debt when your team becomes larger and less experienced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why are there so many?
&lt;/h3&gt;

&lt;p&gt;They are fairly straightforward to write. It seems like each language has their own versions of full logic and semi.  Python and JavaScript seem to be leading the pack with more still being created.&lt;/p&gt;

&lt;p&gt;Another reason is the 'Not Invented Here Syndrome'. Shopify's Liquid and Mozilla's Nunjucks might be guilty of this. Although it is probably more for legal reasons.&lt;/p&gt;

&lt;p&gt;Template engines evolve. For example Twitter liked Mustache, but added template inheritance and wrote Hogan. Ember's Handlebars also built off of Mustache by adding an AST to make sure generated templates are html correct. This is nothing new in the open source world.&lt;/p&gt;

&lt;p&gt;Overall I think the number of template engines is good. A template engine can be very personal. Repeating what I mentioned above, what one person needs in a template engine another may not. Perhaps programmer's just want to scratch an itch.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to choose the one?
&lt;/h3&gt;

&lt;p&gt;You always want to be further away from logic-full as you can. If you can get by with just Mustache and not use lambdas; you should do it. Otherwise Logic-less with some filters/helpers like Liquid and Handlebars is probably the sweet spot.&lt;/p&gt;

&lt;p&gt;But please never go full logic.&lt;/p&gt;

&lt;p&gt;Which one do I like best? None. The current crop of template engines are all adequate, but not perfect. Certainly room for another templating engine.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>templates</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
