<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bukhori M. Aqid</title>
    <description>The latest articles on DEV Community by Bukhori M. Aqid (@bukhorimuhammad).</description>
    <link>https://dev.to/bukhorimuhammad</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%2F408666%2Fb3911e39-5479-4f01-90e8-170a75158082.jpg</url>
      <title>DEV Community: Bukhori M. Aqid</title>
      <link>https://dev.to/bukhorimuhammad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bukhorimuhammad"/>
    <language>en</language>
    <item>
      <title>Making any chrome os device your second screen</title>
      <dc:creator>Bukhori M. Aqid</dc:creator>
      <pubDate>Sat, 06 Mar 2021 04:03:09 +0000</pubDate>
      <link>https://dev.to/bukhorimuhammad/making-any-chrome-os-device-your-second-screen-1nbn</link>
      <guid>https://dev.to/bukhorimuhammad/making-any-chrome-os-device-your-second-screen-1nbn</guid>
      <description>&lt;p&gt;For a while now, I'm trying to make my Lenovo Duet as my portable second screen. I don't want to carry around monitors everywhere and my main devices for traveling are Macbook and Chromebook. That's why I thought it would be cool if I can use my Duet Chromebook as my second screen.&lt;/p&gt;

&lt;p&gt;First, I tried several options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duet Display (&lt;a href="https://www.duetdisplay.com/"&gt;https://www.duetdisplay.com/&lt;/a&gt;) - They have lots of good reviews but unfortunately the connection is not stable and I notice lots of lag. They have pretty good support though and I managed to get a refund. Thanks!&lt;/li&gt;
&lt;li&gt;Synergy (&lt;a href="https://github.com/symless/synergy-core"&gt;https://github.com/symless/synergy-core&lt;/a&gt;) and Barrier (&lt;a href="https://github.com/debauchee/barrier"&gt;https://github.com/debauchee/barrier&lt;/a&gt;) also doesn't work. They crashed when I tried to move my mouse to the chromebook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally I found Deskreen &lt;a href="https://deskreen.com/"&gt;https://deskreen.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to use this app, I need to purchase some hardware (virtual plug) that enables me to extend the screen. However, the result is pretty satisfactory. The connection is stable and even though there are lags, it's still acceptable.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>chromebook</category>
      <category>screen</category>
      <category>development</category>
    </item>
    <item>
      <title>Migrating from JIRA to Redmine</title>
      <dc:creator>Bukhori M. Aqid</dc:creator>
      <pubDate>Fri, 26 Jun 2020 17:09:53 +0000</pubDate>
      <link>https://dev.to/bukhorimuhammad/migrating-from-jira-to-redmine-280k</link>
      <guid>https://dev.to/bukhorimuhammad/migrating-from-jira-to-redmine-280k</guid>
      <description>&lt;p&gt;&lt;em&gt;both are great, really!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MYegljDF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1822/1%2AiERkg5qjTDCTymI7EwCXKw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MYegljDF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1822/1%2AiERkg5qjTDCTymI7EwCXKw.png" alt="redmine minimalist login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the very start, we loved to experiment with tools &amp;amp; new technologies for our project management. We’ve tried &lt;a href="https://asana.com"&gt;Asana&lt;/a&gt;, &lt;a href="https://trello.com"&gt;Trello&lt;/a&gt;, &lt;a href="https://basecamp.com"&gt;Basecamp&lt;/a&gt;, &lt;a href="https://www.smartsheet.com"&gt;Smartsheet&lt;/a&gt;, &lt;a href="https://www.pivotaltracker.com"&gt;Pivotal Tracker&lt;/a&gt;, JIRA Server, Jira Cloud and many other tools. Though we love all of them, we can only use them for short period of time before finding impediments or some features that we think we need but at the time non-existent in that particular platform.&lt;/p&gt;

&lt;p&gt;Last year, we used &lt;a href="https://jira.atlassian.com"&gt;JIRA&lt;/a&gt; for our project management platform. We loved it. JIRA has lots of good features that we want, and we need. Custom workflow, Sprint based planning, informative dashboard, Bitbucket integration and many more. Our only complaint is that it was &lt;a href="https://news.ycombinator.com/item?id=8990990"&gt;quite hard to setup initially&lt;/a&gt;. Aside from that, we love the experience. But as our team grows, somehow we need to re-evaluate our usage on JIRA because of the cost vs benefit that it bring. This year, we grew from 15 to ~23 person team and forecasted to be around 30 at the end of the year. Taking a quick glance at JIRA pricing, we’re going to spend ~$1500 to~$3000 annually. Which is quite pricy for us. And so we began our search…&lt;/p&gt;

&lt;p&gt;After several weeks of comparing JIRA with another tools, we find it hard to replace our daily use cases. But then I remembered &lt;a href="http://www.redmine.org"&gt;Redmine&lt;/a&gt;, a project management tools that I’ve used before in college. The UI is really simple and honestly quite ugly back then, but I’m curious to give it a go since it’s an open source project that I hoped we can tinker with.&lt;/p&gt;




&lt;p&gt;And turns out, we find it quite pleasurable to use because&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There is an awesome theme : &lt;a href="https://github.com/mrliptontea/PurpleMine2"&gt;https://github.com/mrliptontea/PurpleMine2&lt;/a&gt; that really boost the general look &amp;amp; feel ( though we can’t compare it with the final polished commercial product such as JIRA ). We did change the theme a little bit to suit our taste better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A lot of plugins available ( free / commercial ). Those plugin options really helped us take what’s good from JIRA and incorporate them into our Redmine. Even though Redmine has a lot of useful features, but to increase our productivity we decided to install several plugins.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the features that I personally found super useful :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ability to right-click (multiple) task and display quick actions for those following task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3h4NuH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1266/1%2Ar8TTGU_bZ3BQcWu4lbyFAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z3h4NuH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1266/1%2Ar8TTGU_bZ3BQcWu4lbyFAA.png" alt="the right click of awesomeness"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ability to create and categorize Roadmap. You can see spent time, overall progress and deadline for that specific Roadmap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OlRuhgSq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1894/1%2AQr37WLJL8z8x9qTu60gr4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OlRuhgSq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1894/1%2AQr37WLJL8z8x9qTu60gr4A.png" alt="roadmap page detail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parent-Child project relationship. JIRA doesn’t have this and we have some difficulties managing our project relations. Redmine has this feature built in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t13LMMh8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/568/1%2ATXh_ES3w-XRY88x_ffyb1Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t13LMMh8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/568/1%2ATXh_ES3w-XRY88x_ffyb1Q.png" alt="parent-child project relations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some important plugins that we use are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://bitbucket.org/tkusukawa/redmine_work_time"&gt;https://bitbucket.org/tkusukawa/redmine_work_time&lt;/a&gt;
We use this plugin to make worktime log and keeping track of your daily task easier. I personally loved this plugin and use it instead or the original redmine’s time logger.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VL8j-VtF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2814/1%2AzHEvdH_Tx4q_-v9Kq41muw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VL8j-VtF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2814/1%2AzHEvdH_Tx4q_-v9Kq41muw.png" alt="top section is for your recorded time. bottom section is your time tracking form."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/JostBaron/redmine_workload"&gt;https://github.com/JostBaron/redmine_workload&lt;/a&gt;
We use this plugin to view resource workload estimation
&lt;em&gt;Installation notes : after installing, we found some styling conflict and we need to edit the plugins .rb files&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lcZ4RXCB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1664/1%2AGvwUi9EVpPTgt0uMAUrVSg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lcZ4RXCB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1664/1%2AGvwUi9EVpPTgt0uMAUrVSg.png" alt="dat rainbow though"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.redmine.org/plugins/custom-workflows"&gt;http://www.redmine.org/plugins/custom-workflows&lt;/a&gt;
This plugin is really powerful if you understand how to code ( using Ruby ). We used this plugin for task automaton such as automatic assignment, default task properties and other automaton task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DaSThtzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2272/1%2An5JvF6S4JZ19stNoPZ85pg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DaSThtzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2272/1%2An5JvF6S4JZ19stNoPZ85pg.png" alt="several of our automated task"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jgraichen/redmine_dashboard"&gt;https://github.com/jgraichen/redmine_dashboard&lt;/a&gt;
JIRA has a beautiful Kanban board and some of us really missed it because Redmine doesn’t provide this feature. We add this dashboard plugin to cater for those who prefers Kanban board style.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lQqMHmmn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2840/1%2AyXK5xv0oRunKK2Iq1NwE9Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQqMHmmn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2840/1%2AyXK5xv0oRunKK2Iq1NwE9Q.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other plugins that we use are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/akiko-pusu/redmine_issue_templates"&gt;https://github.com/akiko-pusu/redmine_issue_templates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/a-ono/redmine_ckeditor"&gt;https://github.com/a-ono/redmine_ckeditor&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Installation notes : this plugin has conflict with redmine_mentions. if you enable it, mentions can’t be used on the same field.&lt;br&gt;
&lt;a href="https://github.com/a-ono/redmine_ckeditor/issues/113"&gt;https://github.com/a-ono/redmine_ckeditor/issues/113&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/a-ono/redmine_per_project_formatting"&gt;https://github.com/a-ono/redmine_per_project_formatting&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://stgeneral.github.io/redmine-progressive-projects-list/"&gt;http://stgeneral.github.io/redmine-progressive-projects-list/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://rmplus.pro/en/redmine/plugins/usability"&gt;http://rmplus.pro/en/redmine/plugins/usability&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Installation notes : never enable simplified view for participants — will result on 500 error! Also I think there are styling conflicts with PurpleTheme&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/arkhitech/redmine_mentions"&gt;https://github.com/arkhitech/redmine_mentions&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.redmine.org/plugins/redmine_editor_preview_tab"&gt;https://www.redmine.org/plugins/redmine_editor_preview_tab&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vichak/redmine-import-tasks"&gt;https://github.com/vichak/redmine-import-tasks&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Installation notes : create your own public/uploads/exports plugin and make sure www-data has access to it. enable popup for auto download&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even with all of those plugins addition, Redmine still has a lot of things that we need to adjust. But for now, we’re quite satisfied with it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cheers&lt;/em&gt;&lt;/p&gt;

</description>
      <category>jira</category>
      <category>redmine</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>Extending Fabric 2 Test Network</title>
      <dc:creator>Bukhori M. Aqid</dc:creator>
      <pubDate>Thu, 25 Jun 2020 19:55:22 +0000</pubDate>
      <link>https://dev.to/bukhorimuhammad/extending-fabric-2-test-network-50ll</link>
      <guid>https://dev.to/bukhorimuhammad/extending-fabric-2-test-network-50ll</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Fabric 2&lt;/strong&gt;&lt;br&gt;
Hyperledger Fabric is a private blockchain platform that enables you to create permissioned blockchain network. The main elements in Hyperledger Fabric are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Peer &amp;amp; Organization&lt;/strong&gt;: Peer node hosts and execute ledger transactions and smart contracts. Peer belongs to Organization. Some peers can be endorsing peers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orderer&lt;/strong&gt;: Orderer provides ordering service (packages transactions into blocks to be delivered to peers on a channel).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel&lt;/strong&gt;: Channel are logical structure formed by collection of peers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaincode / Smart Contract&lt;/strong&gt;: Smart Contract is software that defines the business logic, contains assets and related transactions. Hyperledger Fabric smart contracts are called chaincode and may specify an endorsement policy which defines transaction validity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach that is taken by Hyperledger Fabric (in my opinion) is beneficial for industrial use cases because it enables cooperation between organization (using channels) while to certain extent having a privacy inside the organization.&lt;/p&gt;

&lt;p&gt;To explore the capabilities of Fabric, there are some examples provided that serves certain use cases. For a simple introduction, there are 2 examples that should be used: First Network and Test Network. Due to a major upgrade in Hyperledger Fabric, there are 2 major versions available 1.4.x and 2.x.x - First Network is suitable if you want to learn Fabric 1.4.x but Test Network would be preferable for Fabric 2.x.x. Also good to know that Test Network is a replacement for First Network so you should use that whenever possible.&lt;/p&gt;

&lt;p&gt;The striking difference between First Network and Test Network is the number of nodes. First Networks comes with 2 peers for each organization, and 5 orderers while Test Network only comes with 1 peer per organization and 1 orderer. This might be limited for some scenario that you want to run. This article will help you extend the test network with some helpful bash scripts. The underlying assumption is that you already have a Test Network running with command &lt;code&gt;./network.sh up createChannel &amp;amp;&amp;amp; ./network.sh deployCC&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;To extend Test Network, we need to extend fabric key with &lt;code&gt;cryptogen&lt;/code&gt;, update &lt;code&gt;system-channel&lt;/code&gt; definition, compose orderer nodes, compose peer nodes, join application channel and deploy the chaincode. For an easy setup, clone &lt;a href="https://github.com/aqidd/fabric-test-network-extended"&gt;this repository&lt;/a&gt; and run &lt;code&gt;./extend-network.sh&lt;/code&gt; after setting up your local Test Network. Or to make things easier, just run &lt;code&gt;./setup-fabric-extended.sh&lt;/code&gt; that will setup local Test Network as well as extends it.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Extending Fabric Key&lt;/strong&gt;&lt;br&gt;
Before extending the network, we need to generate all the necessary key for each new orderer and peer that we want to create. The easiest way to do that is by using &lt;code&gt;cryptogen&lt;/code&gt; command. &lt;code&gt;cryptogen&lt;/code&gt; is an utility for generating Hyperledger Fabric key material. It is provided as a means of preconfiguring a network for testing purposes. It would normally not be used in the operation of a production network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cryptogen extend &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;crypto-config.yaml &lt;span class="nt"&gt;--input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"organizations"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--config&lt;/code&gt; parameter should point to the new network configuration, not the existing test network configuration. In this case, we want a total of 3 orderers, with 3 peers for each organization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;OrdererOrgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Orderer&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
  &lt;span class="na"&gt;EnableNodeOUs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;Specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer1&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer2&lt;/span&gt;

&lt;span class="na"&gt;PeerOrgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Org1&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;org1.example.com&lt;/span&gt;
  &lt;span class="na"&gt;EnableNodeOUs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;Template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;SANS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
  &lt;span class="na"&gt;Users&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Org2&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;org2.example.com&lt;/span&gt;
  &lt;span class="na"&gt;EnableNodeOUs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;Template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;SANS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
  &lt;span class="na"&gt;Users&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Extending Test Network Orderer&lt;/strong&gt;&lt;br&gt;
First, we need to update &lt;code&gt;system-channel&lt;/code&gt; configuration so that we can run new orderer node. The steps needed to update &lt;code&gt;system-channel&lt;/code&gt; are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch (and decode) latest configuration&lt;/li&gt;
&lt;li&gt;Add new orderer certificate generated by &lt;code&gt;cryptogen&lt;/code&gt; to orderer consenters and modify the configuration&lt;/li&gt;
&lt;li&gt;Apply the change to blockchain&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To fetch and decode latest configuration, we need to execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;peer channel fetch config ./out/config_block.pb &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$ORDERER_ADDRESS&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nt"&gt;--tls&lt;/span&gt; &lt;span class="nt"&gt;--cafile&lt;/span&gt; &lt;span class="nv"&gt;$TLS_ROOT_CA&lt;/span&gt;

configtxlator proto_decode &lt;span class="nt"&gt;--input&lt;/span&gt; ./out/config_block.pb &lt;span class="nt"&gt;--type&lt;/span&gt; common.Block &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/config_block.json

jq .data.data[0].payload.data.config ./out/config_block.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./out/config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands above will get the latest config and store the result in &lt;code&gt;out&lt;/code&gt; folder. The default orderer address is &lt;code&gt;export ORDERER_ADDRESS=localhost:7050&lt;/code&gt; and the &lt;code&gt;TLS_ROOT_CA&lt;/code&gt;should be &lt;code&gt;test-network/organizations/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next is adding new orderer certificate to the new configuration. We can achieve that by executing commands below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# add new orderer certificate&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;client_tls_cert&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$ORDERER_TLS&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 0&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;host&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;orderer&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.example.com&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;port&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:7&lt;/span&gt;&lt;span class="nv"&gt;$150&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;server_tls_cert&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$ORDERER_TLS&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 0&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/out/ord&lt;span class="nv"&gt;$1consenter&lt;/span&gt;.json

jq &lt;span class="s2"&gt;".channel_group.groups.Orderer.values.ConsensusType.value.metadata.consenters += [&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ./out/ord&lt;span class="nv"&gt;$1consenter&lt;/span&gt;.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt; ./out/config.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./out/modified_config.json

&lt;span class="c"&gt;# calculate config differences&lt;/span&gt;
configtxlator proto_encode &lt;span class="nt"&gt;--input&lt;/span&gt; ./out/config.json &lt;span class="nt"&gt;--type&lt;/span&gt; common.Config &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/config.pb

configtxlator proto_encode &lt;span class="nt"&gt;--input&lt;/span&gt; ./out/modified_config.json &lt;span class="nt"&gt;--type&lt;/span&gt; common.Config &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/modified_config.pb

configtxlator compute_update &lt;span class="nt"&gt;--channel_id&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nt"&gt;--original&lt;/span&gt; ./out/config.pb &lt;span class="nt"&gt;--updated&lt;/span&gt; ./out/modified_config.pb &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/config_update.pb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$1&lt;/code&gt; refers to our orderer address, &lt;code&gt;$2&lt;/code&gt; refer to channel name (system-channel) and &lt;code&gt;$ORDERER_TLS&lt;/code&gt; should refer to TLS certificate for the corresponding orderer.&lt;/p&gt;

&lt;p&gt;The final step before starting the node is applying the changes via update transaction&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# "applying changes"&lt;/span&gt;
configtxlator proto_decode &lt;span class="nt"&gt;--input&lt;/span&gt; ./out/config_update.pb &lt;span class="nt"&gt;--type&lt;/span&gt; common.ConfigUpdate &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/config_update.json

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"payload":{"header":{"channel_header":{"channel_id":"'&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s1"&gt;'", "type":2}},"data":{"config_update":'&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ./out/config_update.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s1"&gt;'}}}'&lt;/span&gt; | jq &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./out/config_update_in_envelope.json

configtxlator proto_encode &lt;span class="nt"&gt;--input&lt;/span&gt; ./out/config_update_in_envelope.json &lt;span class="nt"&gt;--type&lt;/span&gt; common.Envelope &lt;span class="nt"&gt;--output&lt;/span&gt; ./out/config_update_in_envelope.pb

&lt;span class="c"&gt;# "submit update transaction"&lt;/span&gt;
peer channel update &lt;span class="nt"&gt;-f&lt;/span&gt; ./out/config_update_in_envelope.pb &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$ORDERER_ADDRESS&lt;/span&gt; &lt;span class="nt"&gt;--tls&lt;/span&gt; &lt;span class="nt"&gt;--cafile&lt;/span&gt; &lt;span class="nv"&gt;$TLS_ROOT_CA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is actually creating and running the orderer node. The easiest way is to use docker compose and add the service definition below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;orderer1.example.com&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer1.example.com&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer-base.yaml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer-base&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_LISTENPORT=7150&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${FABRIC_SAMPLES_DIR}/test-network/system-genesis-block/genesis.block:/var/hyperledger/orderer/orderer.genesis.block&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${FABRIC_SAMPLES_DIR}/test-network/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/var/hyperledger/orderer/msp&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${FABRIC_SAMPLES_DIR}/test-network/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/:/var/hyperledger/orderer/tls&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;orderer1.example.com:/var/hyperledger/production/orderer&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;7150:7150&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with &lt;code&gt;orderer-base.yaml&lt;/code&gt; defined below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;orderer-base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hyperledger/fabric-orderer:$IMAGE_TAG&lt;/span&gt;
      &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FABRIC_LOGGING_SPEC=INFO&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_LISTENADDRESS=0.0.0.0&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_GENESISMETHOD=file&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_LOCALMSPID=OrdererMSP&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp&lt;/span&gt;
        &lt;span class="c1"&gt;# enabled TLS&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_TLS_ENABLED=true&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_KAFKA_VERBOSE=true&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]&lt;/span&gt;
      &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/opt/gopath/src/github.com/hyperledger/fabric&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orderer&lt;/span&gt;
      &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;net_test&lt;/span&gt; &lt;span class="c1"&gt;# docker network for Test Network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Extending Test Network Peer&lt;/strong&gt;&lt;br&gt;
Extending peer node is easier. After you've generated all the required key, you can directly compose the node. One of the sample configuration for your node container is given below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;peer1.org1.example.com&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peer1.org1.example.com&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peer-base.yaml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peer-base&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Peer specific variabes&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_ID=peer1.org1.example.com&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_ADDRESS=peer1.org1.example.com:7151&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_LISTENADDRESS=0.0.0.0:7151&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:7152&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7152&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7151&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7151&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_LOCALMSPID=Org1MSP&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/:/host/var/run/&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${FABRIC_SAMPLES_DIR}/test-network/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${FABRIC_SAMPLES_DIR}/test-network/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;peer1.org1.example.com:/var/hyperledger/production&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;7151:7151&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with &lt;code&gt;peer-base.yaml&lt;/code&gt; defined below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;peer-base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hyperledger/fabric-peer:$IMAGE_TAG&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Generic peer variables&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_test&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FABRIC_LOGGING_SPEC=WARN:cauthdsl=info:policies=debug:msp=info&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_TLS_ENABLED=true&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_GOSSIP_USELEADERELECTION=true&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_GOSSIP_ORGLEADER=false&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_PROFILE_ENABLED=true&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt&lt;/span&gt;
        &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/opt/gopath/src/github.com/hyperledger/fabric/peer&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peer node start&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;net_test&lt;/span&gt; &lt;span class="c1"&gt;# docker network for Test Network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's basically it. Make sure that all certificates and keys are pointing in the correct and existing folder and you're good to go.&lt;/p&gt;

&lt;p&gt;Enjoy your new network!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>hyperledgerfabric</category>
      <category>distributedsystems</category>
      <category>fabric</category>
    </item>
    <item>
      <title>Design Patterns in Healthcare domain</title>
      <dc:creator>Bukhori M. Aqid</dc:creator>
      <pubDate>Sun, 07 Jun 2020 13:22:33 +0000</pubDate>
      <link>https://dev.to/bukhorimuhammad/design-patterns-in-healthcare-domain-4lmk</link>
      <guid>https://dev.to/bukhorimuhammad/design-patterns-in-healthcare-domain-4lmk</guid>
      <description>&lt;p&gt;&lt;em&gt;Same old design patterns, from healthcare use cases&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For those of you who don’t know, design pattern is one of the fundamental concepts in software engineering that will help you manage pieces of your system by reducing complexity and isolating independent components so that frequent change can be performed smoothly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A pattern describes a &lt;strong&gt;problem that occurs over and over&lt;/strong&gt; again in our environment, and then &lt;strong&gt;describes the core of the solution&lt;/strong&gt; to that problem in such a way that &lt;strong&gt;you can use this solution a million times&lt;/strong&gt; over, without ever doing it the same way, twice&lt;br&gt;&lt;br&gt;
 — Christopher Alexander, A Pattern language&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz-DBQ6G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/140/1%2AYBbJhIUmblFXyluBa9CWzA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz-DBQ6G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/140/1%2AYBbJhIUmblFXyluBa9CWzA.jpeg" alt=""&gt;&lt;/a&gt;Design Patterns by GoF&lt;/p&gt;

&lt;p&gt;One of the famous books regarding software design pattern is created by Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson &amp;amp; John Vlissides).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iNQv_LLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/113/1%2AqeWhEvXBjWs0IFE9MI8Q3g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iNQv_LLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/113/1%2AqeWhEvXBjWs0IFE9MI8Q3g.gif" alt=""&gt;&lt;/a&gt;A System of Patterns&lt;/p&gt;

&lt;p&gt;There is also a good book by Gang of Five (5 completely different persons than Gang of Four) which gives a bigger scope perspective in software engineering patterns.&lt;/p&gt;

&lt;p&gt;In this series of articles, I will try to dissect and discuss some of the patterns contained in those 2 books with sample cases/problems from the healthcare domain. I do realize that those books discussed more towards the context of Object-Oriented Principle and might not apply in some non Object-Oriented language. But the patterns alone are worth to discuss and might be beneficial in some general cases.&lt;/p&gt;

&lt;p&gt;Before starting the pattern discussions, we have to know how to model real life concept/object type and phenomenon/object instance. We usually model those with UML (Unified Modelling Language) and that’s what we’ll use most of the time while discussing design patterns.&lt;/p&gt;

&lt;p&gt;Since we’re going to work with lots of UML diagram in this article series, let’s recall some of the UML notation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j5_11YLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AK_9IUd6ADpHWSnvva61xUA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j5_11YLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AK_9IUd6ADpHWSnvva61xUA.png" alt=""&gt;&lt;/a&gt;&lt;a href="https://www.omg.org/spec/UML/2.5.1/PDF"&gt;&lt;/a&gt;&lt;a href="https://www.omg.org/spec/UML/2.5.1/PDF"&gt;https://www.omg.org/spec/UML/2.5.1/PDF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will be some UML doodle similar to the one above in this series so bear with my chicken scratch handwriting :)&lt;/p&gt;

&lt;p&gt;Before crafting UML diagram, there are 4 important concepts that you need to remember for modeling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abstraction&lt;/strong&gt; : Can the object instances be generalized into type or sub-type?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inheritance&lt;/strong&gt; : Which type is the ‘parent’ of the other type? (Car vs Sports Car)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encapsulation&lt;/strong&gt; : Which part of the data/behavior is exposed to the outer world?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Polymorphism&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GUADUmRy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AH-oKaSp6iqUcuK9ZbrQbTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GUADUmRy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AH-oKaSp6iqUcuK9ZbrQbTg.png" alt=""&gt;&lt;/a&gt;PSE 1920 TUM: Polymorphism hierarchy&lt;/p&gt;

&lt;p&gt;Besides doing that, you also want to achieve &lt;strong&gt;low coupling and high cohesion.&lt;/strong&gt; Having low coupling means that the dependencies between subsystems are low and high cohesion means that the dependencies among classes in one system are high. To achieve this property there are some things that you can do :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Principle of Least Knowledge/Law of Demeter&lt;/em&gt;&lt;/strong&gt;
The intuition for this is rather easy, if you call multiple objects e.g. objectA.getB.getC.doThings() then you might violate this principle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Ask, don’t tell&lt;/em&gt;&lt;/strong&gt;
Instead of directly modifying object internals (tell), call a method/API that will modify such internal (ask).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In this article, I will take some of the patterns and try to give some context and examples related to healthcare domain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;I. Structural Patterns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This pattern group aims to reduce coupling between classes, enabling future extensions (by introducing abstract class) and encapsulate complex structures.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Delegation Pattern&lt;/strong&gt; on Activity Delegation between Doctor and Nurses
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;In many states, physicians can delegate their activities to nurses, physician assistants or other medical professionals to deliver care more efficiently and effectively.&lt;br&gt;&lt;br&gt;
&lt;a href="http://lawatlas.org/datasets/physician-scope-of-practice-1509022789"&gt;http://lawatlas.org/datasets/physician-scope-of-practice-1509022789&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpVyCBBj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AnwumzZeGi_eHU0hmKGkRVA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpVyCBBj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AnwumzZeGi_eHU0hmKGkRVA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can imagine that during the daily tasks of a doctor, there are some activities that can be delegated to another role that is better suited or even more skilled in that one specific action. That’s why sometimes you have doctor prescribe and/or apply the first medicine but then followed up by nurses.&lt;/p&gt;

&lt;p&gt;We can model that kind of scenario using delegation pattern. Simply by having Doctor class to store reference to Nurse class and when needed, call the Nurse object for action delegation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if (doctor.busy) nurse.apply()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Adapter Pattern&lt;/strong&gt; on API Development in Legacy Hospital System
&lt;/h4&gt;

&lt;p&gt;Consider this scenario:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A hospital has already been running for 100 years with stable in-place system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are a new and modern tech division in the hospital, wants to create mobile app, needing API that consumes the data from legacy system as well as collecting new data from other sources&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G-H5dyOs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AUM-Iw0NgcxLUHn6aU8qHCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G-H5dyOs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AUM-Iw0NgcxLUHn6aU8qHCg.png" alt=""&gt;&lt;/a&gt;some kind of UML Diagram&lt;/p&gt;

&lt;p&gt;One way to connect those 2 systems is to create an adapter. In the UML diagram above, Legacy Adapter acts as a translator/connector between 2 systems. This can be done by implementing interfaces or extending parent class (and override some methods) from the new system and then make a delegation call (blue arrow) or calling the superclass method (inheritance green arrow) to get the value.&lt;/p&gt;

&lt;p&gt;Please be aware that you might need to do some parsing/conversion process in the adapter to ensure that the request and response data is in a valid format.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Bridge Pattern&lt;/strong&gt; on Medicine Procurement from Multiple Sources
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0191778"&gt;Medicine procurement in hospital pharmacies of Nepal: A qualitative study based on the Basel Statements&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It was found that the majority of hospital pharmacies in Nepal reported using an expensive direct-procurement model for purchasing medicines.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since direct-procurement in Nepal is expensive, we want to provide cheaper option by having an auction based or competitive-procurement. But we don’t want to disrupt an already stable system. There is also a problem that some branches might already have their own customization. This calls for a Bridge Pattern.&lt;/p&gt;

&lt;p&gt;In this scenario, our Bridge Pattern consists of&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Domain:
This is your hospital/hospital system&lt;/li&gt;
&lt;li&gt;Solution Domain:
This is where you get your medicines using some procurement model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Procurement can happen with direct or competitive procurement model, and in this case each hospital branch have the the liberty to choose any model they prefer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5Xyhjktl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AfUjHxqg6mUL3fNOuAEuDHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5Xyhjktl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AfUjHxqg6mUL3fNOuAEuDHg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By creating a bridge pattern between abstraction of hospital and procurement, we can strictly define each branch to have procurement model but since the subclass can override the superclass then each branch can choose their preferred model and new branch can also choose their preferred model. Changing model also easy, just add implementation of procurement and change branch that wants to use that new model.&lt;/p&gt;

&lt;p&gt;But be careful with &lt;strong&gt;Degenerate Bridge&lt;/strong&gt; : where the application or the solution domain doesn’t have a subclass/subtype (yet). This might increase complexity without any clear benefits.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a sense, Adapter pattern might seem similar to Bridge pattern. But “Adapter makes things work after they’re designed; Bridge makes them work before they are. [GoF, p219]”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Proxy Pattern&lt;/strong&gt; on Patient’s Guardian/Decision Proxy
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://hhma.org/blog/why-all-adults-need-a-health-care-proxy/"&gt;Why all adults need a healthcare proxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The article above argues that we should always have a healthcare proxy in for emergency cases. As a healthcare system developer, we want to cater to this scenario hence we’ll implement Proxy Pattern in our hospital system.&lt;/p&gt;

&lt;p&gt;There are 3 types of Proxy Pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caching/Remote Proxy
The proxy object is used for information caching (local representative for an object in a different location)&lt;/li&gt;
&lt;li&gt;Substitute/Virtual Proxy
This proxy is used for a stand-in object in case the real object takes quite a lot of time/memory to instantiate&lt;/li&gt;
&lt;li&gt;Access Control/Protection Proxy
This proxy provides access control to the real object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this particular case, the guardian acts as access control proxy. If the real patient can actually do / willing to do said action that it will do it otherwise the proxy gets to decide.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ac_zM2sa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/941/1%2AIIEEriq9Dep4oq3MgAMGpA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ac_zM2sa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/941/1%2AIIEEriq9Dep4oq3MgAMGpA.png" alt=""&gt;&lt;/a&gt;scratch UML for proxy pattern&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if (competent) inPatient.agreeToProcedure()&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;else patientP&lt;/strong&gt; roxy.agreeToProcedure()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;II. Behavioral Patterns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By applying patterns in this group you can answer “Who does what?” questions, e.g which algorithm is used for some problems, or which object instance to use. This will also simplify control flow and enable a better understanding of your program data flow.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Strategy Pattern&lt;/strong&gt; on Patient-Centered Care approach
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/16965313"&gt;Eliciting patient treatment preferences: A strategy to integrate evidence-based and patient-centered care.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the strategy described in article above is to elicit patient preferences via written description. With some preferences given, there will be differences in patient care/treatment. During the hospital system development, this scenario can be handled by utilizing strategy pattern&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xRpQfCSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFXbG00-7AzlCI46xz-i2vw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xRpQfCSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFXbG00-7AzlCI46xz-i2vw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The difference with Bridge Pattern is that if you use a bridge pattern, the patient (depending on the preference) will receive the type of treatment that he/she wants before system runtime while in strategy pattern, the treatment will be decided from patient preferences and can be changed at runtime if the preferences of the patient changed.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;State Pattern&lt;/strong&gt; on Medical State representation
&lt;/h4&gt;

&lt;p&gt;Sometimes, hospital describe patient’s condition in a medical state jargon. Even though this is not commonly used clinical term, it will serve as a nice example for the needs of using State Pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Medical_state"&gt;Medical state&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;State Pattern is used to help object control their behavior by changing its internal state.&lt;/p&gt;

&lt;p&gt;Per Wikipedia’s description, there are several Medical States:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Undetermined&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Patient awaiting physician and/or assessment.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Good&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Vital_signs"&gt;Vital signs&lt;/a&gt; are stable and within normal limits. Patient is conscious and comfortable. Indicators are excellent.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Fair&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Vital signs are stable and within normal limits. Patient is conscious, but may be uncomfortable. Indicators are favorable.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Serious&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Vital signs may be unstable and not within normal limits. Patient is seriously ill. Indicators are questionable.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Critical&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Vital signs are unstable and not within normal limits. Patient may be unconscious. Indicators are unfavorable.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Dead&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Vital signs have ceased. Patient has died.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MIxD2knp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2As8YbNaB5odDnhV720FD7ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MIxD2knp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2As8YbNaB5odDnhV720FD7ug.png" alt=""&gt;&lt;/a&gt;scratch UML for Medical State&lt;/p&gt;

&lt;p&gt;Every state can move to another state depending on the patient’s condition.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;patientState.handle(…) can results in different actions depending on the current Medical State&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There might be a question on where to handle state change, should it happen in the context class (TreatmentContext) or should it happen in concrete class (Medical States). I would say that this is up to personal preferences, but handling it in the concrete class will reduce the conditional block and making it simpler to add more state and/or see the limitation on each state.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Observer Pattern&lt;/strong&gt; on Integrated Patient Information
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.researchgate.net/publication/220796284_A_mediated_publish-subscribe_system_for_inter-institutional_process_support_in_healthcare"&gt;Inadequate availability of patient information is a major cause for medical errors and aﬀects costs in healthcare. Traditional information integration in healthcare does not solve the problem.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An improvement for the information exchange is needed. The goal is to provide better information exchange between institutions (see Broker Pattern), or in smaller cases — between displays in a hospital counter. Let’s discuss the this smaller scope using observer pattern.&lt;/p&gt;

&lt;p&gt;There are 2 key parts in observer pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observable object / Publisher&lt;/li&gt;
&lt;li&gt;Observers / Subscribers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine that in the same examination room, you have different screen / Graphical User Interface (GUI) used by the nurse to take your blood pressure, check for previous diseases, etc. There is also another GUI for the doctor to input more extensive treatment and diagnosis.&lt;br&gt;&lt;br&gt;
Wouldn’t it be nice if when the nurse enters your measured data, the GUI for the doctor is also updated? We can achieve this by applying an observer pattern with patient information as observable object&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iKNWJGVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AE5mcqOBNpNF_AJ7zyemxEw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iKNWJGVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AE5mcqOBNpNF_AJ7zyemxEw.png" alt=""&gt;&lt;/a&gt;scratch UML for publish-subscribe scenario&lt;/p&gt;

&lt;p&gt;Each GUI must have Observer implementation so that they can observe the patient information. And since they also modifying the Observable object, all changes will be observed and updated by other GUIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;III. Creational Patterns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes to create something there are complex process involved and Creational Patterns are one collection of design pattern trying to improve the implementation of those complex processes. By applying patterns in this group you can create a simplified view to understand those processes in a glance. This will also make the creation process independent hence reducing dependency and coupling.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Abstract Factory Pattern&lt;/strong&gt; on Doctor Skills Composition
&lt;/h4&gt;

&lt;p&gt;Doctor can have multiple skill set. How do we properly model this scenario using Abstract Factory pattern?&lt;/p&gt;

&lt;p&gt;Before starting with this pattern, we need to address the difference between Factory (Method) pattern vs Abstract Factory pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factory Method&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
As the name implies, Factory Method is a method / function that has an objective to instantiate one object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Utilizing full class as Abstract Factory, we can create more complex object instantiation consisting of different classes composing that said object.&lt;/p&gt;

&lt;p&gt;Now let’s consider the action of adding new doctor to the hospital. Every doctor has their degree and specialization and we might encounter one situation where we have a very competent doctor with multiple and maybe specialized skills. How can we create new doctor object with all the skills information and dependencies?&lt;/p&gt;

&lt;p&gt;In this case, we can generalize few things, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hospital has doctors&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Doctor&lt;/em&gt; has &lt;em&gt;Degree&lt;/em&gt;(s)&lt;/li&gt;
&lt;li&gt;Degree has a specific &lt;em&gt;Degree Factory&lt;/em&gt; extending default (general physician) degree factory&lt;/li&gt;
&lt;li&gt;Degree factory returns degree containing multiple skills given specific factory class&lt;/li&gt;
&lt;li&gt;For a new degree, it’s as easy as add new degree factory with &lt;em&gt;composeSkills()&lt;/em&gt; method containing all the required skills&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NMcbi1LC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ApahWkDJjiqYhkULTooHywg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NMcbi1LC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ApahWkDJjiqYhkULTooHywg.png" alt=""&gt;&lt;/a&gt;scratch UML for Abstract Factory Pattern&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;IV. Architectural Patterns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An architectural pattern is a special set of pattern applied to software architecture problem within a given context. In this section we will discuss several samples of Architectural Pattern.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Blackboard System&lt;/strong&gt; for Evidence-Based Diagnosis
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.degruyter.com/view/j/dx.2014.1.issue-1/dx-2013-0003/dx-2013-0003.xml"&gt;Understanding evidence-based diagnosis : Diagnosis&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“ How do we minimize the cognitive errors inherent to a task like diagnosis? The answer is even less clear, but computerized diagnostic support tools may have a role.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One approach to model computerized diagnostic support is by using Blackboard (behavioral) pattern implemented in Blackboard system (architecture). Intuitively, you can imagine blackboard system as a room filled with experts discussing problems and putting solutions and opinions in the blackboard to achieve one final consensus/result.&lt;/p&gt;

&lt;p&gt;In general, blackboard system consists of 3 big elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blackboard&lt;/strong&gt; is the repository of the problem, partial solutions and new information (hypotheses, etc)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Source&lt;/strong&gt; that reads anything placed in the blackboard (input) and place new information created by them on the blackboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control&lt;/strong&gt; that governs the flow of problem-solving activity in the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also in order to create blackboard system, there are 6 steps that will be beneficial to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define the problem (and make sure there’s no algorithmic solution for it)&lt;/li&gt;
&lt;li&gt;Define the solution space&lt;/li&gt;
&lt;li&gt;Identify Knowledge Sources&lt;/li&gt;
&lt;li&gt;Define the Blackboard&lt;/li&gt;
&lt;li&gt;Define the Control&lt;/li&gt;
&lt;li&gt;Implement Knowledge Sources&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s apply those 6 steps in our case&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The problem : Evidence based diagnosis
Domain: Healthcare
Requirement: Given symptoms, patient health data &amp;amp; history, provide supporting diagnosis output
Actors: Doctor, Patient, Nurses&lt;/li&gt;
&lt;li&gt;Solution space :
In the solution space, we need to identify the existence of top-level and intermediate solutions. A top level solution might indicate a flu diagnosis while intermediate solution might specify more details like possibility of dengue fever.
For a complex diagnosis, partial solution might be needed as well. Such as giving cluster of diseases might occur given the observed symptoms and patient’s history.&lt;/li&gt;
&lt;li&gt;Knowledge Sources:
Different records of past diagnosis, organized (e.g. grouped by city)
Inputs: Patient health data, Reported symptoms
Outputs: Solution candidate as different diagnosis with confidence level&lt;/li&gt;
&lt;li&gt;Defining Blackboard:
We need to decide the data representation used in the blackboard, such as JSON with added metadata.&lt;/li&gt;
&lt;li&gt;Defining Control:
How are we going to process all the data provided from various Knowledge Sources? How and who are going to construct and verify the hypothesis? What constitutes an acceptable solution?
In this stage, an expert help is necessary so collaboration is a must.&lt;/li&gt;
&lt;li&gt;Knowledge Source implementation
To implement Knowledge Sources, we need to define condition and action. We can utilize multiple arrays of techniques such as Bayes rules, classification algorithms, rule based system, or any of the computational intelligence methods.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jw_l3dod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ABGT7v2GPAjM1tAkv9IAaEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jw_l3dod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ABGT7v2GPAjM1tAkv9IAaEQ.png" alt=""&gt;&lt;/a&gt;scratch UML for Blackboard System&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Client-Dispatcher-Server&lt;/strong&gt; for System with High Availability
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Once, I visited a clinic because I got a fever. Their system is under maintenance from 11:00–13:00 and I need to wait until it’s up before my medical data can be processed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;True story. And we can avoid that by implementing simple client-dispatcher-server&lt;/p&gt;

&lt;p&gt;Healthcare is a critical field. A single mistake can cost human life. When I check myself in that said clinic during mid day, I observed that they have tablets and laptop but not using it. Curious, I asked: why do you have those devices but not using it? Surprisingly they said: Our system is usually under maintenance during this time so just to be safe we use paper and we will process the data later. Of course there might be multiple reasons why this happen but having only one server without backup might be the cause, so when there is a scheduled update then the client will be unable to connect to that server. We should provide several servers as backup so we can have zero down time deployment and update. But how are we going to manage those servers and the client connections?&lt;/p&gt;

&lt;p&gt;Client-Dispatcher-Server architecture will help manage your system by introducing a dispatcher subsystem that manages connection between multiple clients and multiple servers so that updates can be done without making the server down.&lt;/p&gt;

&lt;p&gt;To implement Client-Dispatcher-Server there are some steps that is useful to follow&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify subsystem that act as clients, servers and dispatchers&lt;/li&gt;
&lt;li&gt;Decide on the communication mechanism to be used for the protocols&lt;/li&gt;
&lt;li&gt;Specify the protocols between components&lt;/li&gt;
&lt;li&gt;Decide naming scheme for dispatcher&lt;/li&gt;
&lt;li&gt;Implement the dispatcher&lt;/li&gt;
&lt;li&gt;Implement client and server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: To be technically accurate, client-dispatcher-server architecture should enable direct client-server connection after name resolve so if you’re using load balancer to manage multiple servers you need to configure direct server return (&lt;a href="https://www.haproxy.com/blog/layer-4-load-balancing-direct-server-return-mode/"&gt;https://www.haproxy.com/blog/layer-4-load-balancing-direct-server-return-mode/&lt;/a&gt;), sticky session or the combination. But in real life this usually doesn’t matter much.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Broker Pattern&lt;/strong&gt; for Integrated Patient History
&lt;/h4&gt;

&lt;p&gt;While in Observer Pattern we discuss how each hospital units keep it touch with the data, there is also the need to have integrated patient history between hospitals which means all data must be passed remotely. The question is, how to accommodate this use case in our system?&lt;/p&gt;

&lt;p&gt;Broker Pattern, specifically message broker pattern can be used in this scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Message_broker"&gt;Message broker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While implementing the pattern you need to provide client proxy and server proxy in order to make sure that there is no compatibility problem between different platforms and implementations as well as hiding inter-process communication details between said party to broker. The proxy will also takes care of marshaling (serialize) and unmarshaling (deserialize) messages.&lt;/p&gt;

&lt;p&gt;There are lots of existing libraries / tools that can help you with the implementation of message broker pattern. Some of the most popular ones are &lt;a href="https://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt; and &lt;a href="https://kafka.apache.org/"&gt;Apache Kafka&lt;/a&gt;, among many others.&lt;/p&gt;

&lt;p&gt;By understanding several different patterns and actively implement them, we should develop an intuition on how to solve some problems. There are a lot more patterns than described in this article and I personally recommend &lt;a href="https://sourcemaking.com/"&gt;SourceMaking&lt;/a&gt;as your first stop on understanding further patterns. But we have to be careful to not fall into AntiPatterns trap, especially since &lt;a href="https://www.linkedin.com/pulse/anti-pattern-how-obvious-bukhori-aqid/"&gt;sometimes, detecting Anti Pattern is hard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hope this helps!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>softwaredesignpattern</category>
      <category>softwaredevelopment</category>
      <category>healthtechnology</category>
      <category>antipattern</category>
    </item>
    <item>
      <title>Benefits of Pull Request Workflow</title>
      <dc:creator>Bukhori M. Aqid</dc:creator>
      <pubDate>Sun, 28 Jan 2018 17:50:08 +0000</pubDate>
      <link>https://dev.to/bukhorimuhammad/benefits-of-pull-request-workflow-3iei</link>
      <guid>https://dev.to/bukhorimuhammad/benefits-of-pull-request-workflow-3iei</guid>
      <description>&lt;p&gt;&lt;em&gt;From no workflow to gitflow to pull requests. Here’s our story…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Initially, we don’t use Git for our projects. Around 2010, SVN is our main source control / versioning ( aside from Dropbox and USB Drive transfer 🤘 ). After we grow into several people working in the same project, several discomforts occurred and we decided to adopt Git around 2013.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yo-e0r9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMH8tjxbqlE0KeCSmDC4QXA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yo-e0r9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMH8tjxbqlE0KeCSmDC4QXA.jpeg" alt=""&gt;&lt;/a&gt;finding commits for old feature got us like…&lt;/p&gt;

&lt;p&gt;As usual, the first time is a mess. Several projects have messed up git history that made tracking and merging painful to do. We don’t have any consensus on how to divide branches, or any decent workflow to implement. People just do commit and push as they like. Finally in late 2014 we decided to adopt &lt;a href="https://danielkummer.github.io/git-flow-cheatsheet/"&gt;gitflow&lt;/a&gt; into our workflow. Things got better real quick. We know what to track, who’s doing what and the current branch status.&lt;/p&gt;

&lt;p&gt;But there are still some pain points that we encounter, especially regarding our junior developers. To make a clear and readable branch history, sometimes squash / rebase / rewrite remote history is necessary. And since we don’t protect the develop / master branch sometimes the history got messed up real quick.&lt;/p&gt;

&lt;p&gt;In 2016 we’re starting to actively release our own &lt;a href="https://www.linkedin.com/pulse/flipboxs-contributions-web-technology-bukhori-aqid/"&gt;libraries&lt;/a&gt; and little by little using Pull Request as a way to manage our open source library updates. And surprisingly in 2017, several of our developers suggested that we use Pull Request workflow to replace gitflow.&lt;/p&gt;

&lt;p&gt;To be honest, I was against Pull Request at first. The main reason is that it might introduce bottleneck especially when the reviewer is busy. Deciding the workflow is also requires some discussions ( should we use multiple repo? or one repository with protected branches? how to name branches? etc. ). But in the end after weighing the benefits vs drawbacks I decided to implement Pull Request workflow in some of our projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result is incredible.&lt;/strong&gt; The benefits totally outweigh the drawbacks. Let’s discuss them in details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Pull Request Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean git history
by using pull request, we can easily squash those redundant / unimportant / unclear commits before merging into main branch. This is enforced by our protected branch policy. Only the lead / captain can merge into main branch. Other developers are free to do whatever they want in their branches&lt;/li&gt;
&lt;li&gt;Meaningful git history
we used to neglect this one aspect but turns out this is more important than we think. By adhering with our branch naming convention, all pull requests and merge(s) becomes easier to read and provide features / fixes history. In the end, your git history can be a tools to track productivity and/or project velocity.&lt;/li&gt;
&lt;li&gt;Remote code review process
before pull request, we did code review face to face either by pair programming or code presentation session. Using pull request as our workflow, code review can be done before pull request is merged. This enable smooth code review process, even while doing remote work.&lt;/li&gt;
&lt;li&gt;Better software quality
making pull request means that the feature need to be approved by captain / lead &lt;strong&gt;and&lt;/strong&gt; QA / QC. Before pull request, all features and fixes can be merged to main branch hence updating staging server without the knowledge of QA / QC. This makes testing harder because there is no way to ensure the staging server state. Doing pull requests means that staging server state will only be updated after all changes are approved by lead &amp;amp; QA. This ensures that all codes in our staging server is already inspected by several stakeholders hence better quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks of Pull Request Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long review process
especially when the captain / lead is busy. otherwise, all is well.&lt;/li&gt;
&lt;li&gt;Time / process overhead
there are some complaints that doing pull request resulting in more process to be done. You need to create a pull request in browser, adding comments &amp;amp; change logs, waiting &amp;amp; fixing for feedbacks etc. Sometimes an idle time happens because the developer is waiting for approval and cannot start working on new branch. We discourage working on parallel branches because we believe that focus is important.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though we successfully implement pull request workflow in some of our projects, a detailed guide is necessary to ensure that no redundancy / misconception happened. After several discussions we came up with this &lt;a href="https://github.com/flipboxstudio/tech-handbook/blob/master/pull-request-workflow.md"&gt;workflow conventions&lt;/a&gt;. Feel free to give your feedbacks and inputs on this matter!&lt;/p&gt;

&lt;p&gt;After adopting pull request workflow with additional conventions above, I definitely can say that our projects have been better overall. There might be some problems here and there, but the benefit is really apparent. I suggest that you try to use this approach at least for comparison with your current workflow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cheers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;disclaimer : This post is based on my personal experience while working with&lt;/em&gt; &lt;a href="http://flipbox.co.id"&gt;&lt;em&gt;Flipbox&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Our daily activities and projects is revolving around mobile apps &amp;amp; (sometimes) websites for clients. Those points and suggestions might not apply in a different circumstances.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>teamwork</category>
      <category>git</category>
      <category>pullrequest</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
