<?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: Ball Weera Kasetsin</title>
    <description>The latest articles on Forem by Ball Weera Kasetsin (@ballweera).</description>
    <link>https://forem.com/ballweera</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%2F121683%2Fbe524365-43d6-47ab-b543-c87465d2c4ef.jpeg</url>
      <title>Forem: Ball Weera Kasetsin</title>
      <link>https://forem.com/ballweera</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ballweera"/>
    <language>en</language>
    <item>
      <title>Refactor Go Package by Using gomvpkg</title>
      <dc:creator>Ball Weera Kasetsin</dc:creator>
      <pubDate>Wed, 24 Apr 2019 02:08:44 +0000</pubDate>
      <link>https://forem.com/ballweera/refactor-go-package-by-using-gomvpkg-298a</link>
      <guid>https://forem.com/ballweera/refactor-go-package-by-using-gomvpkg-298a</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rwG7ZFsR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5nla674c0iyppohfafus.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rwG7ZFsR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5nla674c0iyppohfafus.jpeg" alt="Gopher"&gt;&lt;/a&gt;&lt;/p&gt;
https://blog.golang.org/gopher



&lt;p&gt;Go provides a lot of tools to help Go developers. They help Go developers to be productive when they are trying to solve their problems with Go. You can see the list of tools at &lt;a href="https://godoc.org/golang.org/x/tools"&gt;https://godoc.org/golang.org/x/tools&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I've seen many developers that moved from other technology stacks (Java Spring, Ruby on Rails, etc.) use the previous project structure from those to Go project. Layer-based is the one example (controller, model, service, common, util, repository, etc.). In Go, mostly, we will not do that. When we design a Go package (structure), we think about what it provides, not what it contains. And how we use them. You can read my blog about &lt;a href="https://dev.to/ballweera/go-package-structure-design-b0m"&gt;Go Package (Structure) Design&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may know, it is painful when you are trying to refactor legacy Go package. Especially, packages like common, util, base. Because it has been used around the project (other packages use them by importing). If you refactor those packages, you need to put a lot of effort to change the import path in every derived package.&lt;/p&gt;

&lt;p&gt;Actually, there is a Go tool for this situation. It is &lt;strong&gt;gomvpkg&lt;/strong&gt;.&lt;a href="https://godoc.org/golang.org/x/tools/cmd/gomvpkg"&gt;https://godoc.org/golang.org/x/tools/cmd/gomvpkg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to show you how to refactor legacy Go package by using &lt;code&gt;gomvpkg&lt;/code&gt;. We have the package &lt;code&gt;common/consumer&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can see that &lt;code&gt;github.com/ballweera/play-gomvpkg/common/consumer&lt;/code&gt; has been used in only two places (&lt;code&gt;event.go&lt;/code&gt; and &lt;code&gt;main.go&lt;/code&gt;). But in a large program, it may be used more than 10 or 20 times. So it is a bit difficult to refactor and take time to refactor them.&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;gomvpkg&lt;/code&gt;, we can execute only one command to change from &lt;code&gt;github.com/ballweera/play-gomvpkg/common/consumer&lt;/code&gt; to &lt;code&gt;github.com/ballweera/play-gomvpkg/kafka&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After executing &lt;code&gt;gomvpkg&lt;/code&gt;, you would see the result like this&lt;/p&gt;

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


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, in &lt;code&gt;event.go&lt;/code&gt; and &lt;code&gt;main.go&lt;/code&gt;, the import path is changed to &lt;code&gt;github.com/ballweera/play-gomvpkg/kafka&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One thing you need to know about &lt;code&gt;gomvpkg&lt;/code&gt;. It could not be run outside &lt;code&gt;GOPATH&lt;/code&gt;. So you need to move your Go project to &lt;code&gt;GOPATH&lt;/code&gt; before using it. And if you use &lt;code&gt;Go Module (go.mod)&lt;/code&gt;, you also need to set &lt;code&gt;GO111MODULE=auto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I already created the repo to play the &lt;strong&gt;gomvpkg&lt;/strong&gt; &lt;a href="https://github.com/ballweera/play-gomvpkg"&gt;https://github.com/ballweera/play-gomvpkg&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have fun!!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Go Package (Structure) Design</title>
      <dc:creator>Ball Weera Kasetsin</dc:creator>
      <pubDate>Tue, 23 Apr 2019 02:39:23 +0000</pubDate>
      <link>https://forem.com/ballweera/go-package-structure-design-b0m</link>
      <guid>https://forem.com/ballweera/go-package-structure-design-b0m</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SiNbBAvs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1512418490979-92798cec1380%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D1500%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SiNbBAvs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1512418490979-92798cec1380%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D1500%26q%3D80" alt="Package"&gt;&lt;/a&gt;Photo by Leone Venter on Unsplash&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good package name tells you what it provides, not what it contains&lt;br&gt;
-- Practical Go, Dave Cheney&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I do believe in User-Centric Design. It is not only about UX/UI. It is about how things will be used. So when I create functions, programs, APIs, I always think about how to use them. And this is why I love Test-Driven Development (TDD) methodology as well because it encourages me to think about how my function will be used (with tests).&lt;/p&gt;




&lt;p&gt;The package is the unit in a Go program that other packages or modules use it. When I create a package, I'll ask how this package will be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Go, we always use functions through the package.
&lt;/h2&gt;

&lt;p&gt;The package name is essential in Go. So this is the guideline,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The package name must be unique in your Go program&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have found that packages name have been used multiple time in your Go program, those packages would be too generic, or there is some design problem that needs to validate.&lt;/p&gt;

&lt;p&gt;To demonstrate creating a Go package, think about shopping cart on e-commerce. I'm going to provide "add to cart" function. I've started with the cart package.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you create a Go package, always put Go file with the same name as a package name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every time I create a new package, I always put Go file with the same name as the package name. And I'll maintain all functionality of this package in this Go file until I understand the boundary of this package, then use another Go files to re-organize this package. If some feature doesn't make sense to be in this package, I'll move it to a new package.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;From the code snippet, two entities need to consider; Cart and Product. Cart is the receiver of Add method, so I create Cart struct. And also generate Product struct. From this point, I create the "New" function that will return a Cart.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;When you want a cart, you can call New function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;c := cart.New()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is quite natural and readable in my point of view.&lt;/p&gt;

&lt;p&gt;Think about creating a new product. You would have seen &lt;code&gt;pd := cart.NewProduct()&lt;/code&gt;. As I mentioned, the package name will tell you what it provides. From my perspective, the cart should not be responsible for proving the product's functionality. So I decided to create a new package; product and move Product to a new one. When you want to create a product, you can call New function from the product package like &lt;code&gt;pd := product.New()&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;h2&gt;
  
  
  Keep using Go file to re-organize your package, use sub-package when it makes sense
&lt;/h2&gt;

&lt;p&gt;In the Go program, mostly, we don't call a package function with package chaining like this; &lt;code&gt;net.http.Get("http://www.example.com")&lt;/code&gt;. So we need to keep the package name being unique in the Go program. We can create sub-package if it is reasonable. the net/http is an excellent example for sub-package.&lt;/p&gt;

&lt;p&gt;So when you want to re-organize data in your package, you can use Go file to group related data and function and give the meaningful name to a file. Let's see this example&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;common/kafka/producer&lt;br&gt;
common/kafka/consumer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From that design, when you want to create a producer or a consumer, you will use &lt;code&gt;pdc := producer.New()&lt;/code&gt; and &lt;code&gt;csm := consumer.New()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It seems to be OK. But it loses the context. What do the producer and consumer mean?&lt;/p&gt;

&lt;p&gt;One thing I want to mention is&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Avoid package name like base, common, or util&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those packages are too generic. If there is something you would reuse, you will put them to those packages. And then the package name cannot tell you what it provides.&lt;/p&gt;

&lt;p&gt;So I decide to refactor the above package to this&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt; 

&lt;p&gt;Then you can create a producer and consumer with &lt;code&gt;pdc := kafka.NewProducer()&lt;/code&gt; and &lt;code&gt;csm := kafka.NewConsumer()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When you face that your package keeps growing, you can use Go file to re-organize data and functionality. From the previous example, I'll create producer.go and consumer.go to organizer data and functionalities of a producer and a consumer instead of creating sub-package.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;&lt;a href="https://cdn-images-1.medium.com/max/1600/1*UCYQJH_6v7fLx0VijyvRPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://cdn-images-1.medium.com/max/1600/1*UCYQJH_6v7fLx0VijyvRPw.png" alt="Go program structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the time, I don't design all packages of Go program in the first place. But I will think about how the package will be used and what it should provide.&lt;/p&gt;

&lt;p&gt;I hope you will have fun to create software that improves our user's life gets better.&lt;/p&gt;


</description>
      <category>go</category>
      <category>godesign</category>
    </item>
  </channel>
</rss>
