{"id":363878,"date":"2024-05-21T02:05:28","date_gmt":"2024-05-21T02:05:28","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=363878"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T02:05:28","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=363878","title":{"rendered":"<span>Thoughts and short notes (in go) after reading \u00abClean Code\u00bb<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>1. Clean Code<\/strong><\/p>\n<p><em>The gist<\/em>: Clean code is more than just working code; it&#8217;s code that other developers can easily read, understand, and modify.<\/p>\n<pre><code class=\"go\">\/\/ Not so clean func p(a []int) {   \/\/ ...some cryptic code... } \/\/ Clean func sortNumbers(numbers []int) {   \/\/ sorting logic... } <\/code><\/pre>\n<p><strong>2. Meaningful Names<\/strong><\/p>\n<p> <em>The gist<\/em>: Use descriptive and specific names that reveal your intention.<\/p>\n<pre><code class=\"go\">\/\/ Confusing var d int \/\/ elapsed time in days \/\/ Clear var elapsedTimeInDays int \/\/ Even clearer in context func calculateElapsedTime(startDate, endDate time.Time) int {   return int(endDate.Sub(startDate).Hours() \/ 24) } <\/code><\/pre>\n<p><strong>3. Functions<\/strong><\/p>\n<p> <em>The gist<\/em>: Functions should do one thing, be small, and have no side effects.<\/p>\n<pre><code class=\"go\">\/\/ Too complex func handleHttpRequest(r http.Request) { \/\/ parsing, logging, and handling... } \/\/ Decomposed into focused functions func parseRequest(r http.Request) RequestData {...} func logRequest(data RequestData) {...} func handleRequest(data RequestData) Response {...} <\/code><\/pre>\n<p><strong>4. Comments<\/strong><\/p>\n<p> <em>The gist<\/em>: Good code mostly speaks for itself.<\/p>\n<pre><code class=\"go\">\/\/ Unnecessary \/\/ Check if user is valid if user.IsValid() {...} \/\/ Clear code if user.IsValid() {...} \/\/ No comment needed <\/code><\/pre>\n<p><strong>5. Formatting<\/strong><\/p>\n<p><em>The gist<\/em>: Consistent and thoughtful formatting makes your code easier to read and understand.<\/p>\n<pre><code class=\"go\">\/\/ Inconsistent func foo() {   var x int   x=3   fmt.Println(x) } \/\/ Consistent func formatNumber(number int) string {   formatted := fmt.Sprintf(\"%03d\", number)   return formatted } <\/code><\/pre>\n<p><strong>6. Objects and Data Structures<\/strong><\/p>\n<p><em>The gist<\/em>: Objects hide their data behind abstractions and expose functions to operate on that data. Data structures expose their data and have no significant behavior.<\/p>\n<pre><code class=\"go\">\/\/ Data structure type Rectangle struct {   Width  float64   Height float64 } \/\/ Object-like behavior type Shape interface {   Area() float64 } func (r Rectangle) Area() float64 {   return r.Width * r.Height } <\/code><\/pre>\n<p><strong>7. Error Handling<\/strong><\/p>\n<p><em>The gist<\/em>: Treat error handling as a primary concern, not an afterthought.<\/p>\n<pre><code class=\"go\">func connectDatabase(connectionString string) (*sql.DB, error) {   db, err := sql.Open(\"postgres\", connectionString)   if err != nil {     return nil, fmt.Errorf(\"error connecting to database: %v\", err)   }   \/\/ Additional connection verification...   return db, nil } <\/code><\/pre>\n<p><strong>8. Boundaries<\/strong><\/p>\n<p><em>The gist<\/em>: Respect boundaries between different layers and services by keeping interchanges well-defined and clean.<\/p>\n<pre><code class=\"go\">\/\/ Interfacing with an external package func readConfigFile(path string) (Config, error) {   var config Config   data, err := ioutil.ReadFile(path)   if err != nil {     return config, err   }   err = json.Unmarshal(data, &amp;config)   return config, err } <\/code><\/pre>\n<p><strong>9. Unit Tests<\/strong><\/p>\n<p><em>The gist<\/em>: Tests keep your code flexible, maintainable, and understandable.<\/p>\n<pre><code class=\"go\">func TestCalculateTotal(t *testing.T) {   total := calculateTotal([]int{10, 20, 30})   if total != 60 {     t.Errorf(\"Expected 60, got %d\", total)   } } <\/code><\/pre>\n<p><strong>10. Classes (Structs and Interfaces in Go)<\/strong><\/p>\n<p><em>The gist<\/em>: Keep your data structures small, focused, and with a clear purpose.<\/p>\n<pre><code class=\"go\">type Server interface {   Start()   Stop() } type HttpServer struct {   \/\/ Server configuration fields } func (h *HttpServer) Start() {   \/\/ start server } func (h *HttpServer) Stop() {   \/\/ stop server } <\/code><\/pre>\n<p><strong>11. Systems<\/strong><\/p>\n<p><em>The gist<\/em>: Building clean systems involves organizing code into layers and managing dependencies carefully.<br \/> <em>Conceptual Example<\/em>:<br \/> Organize your code into packages with clear purposes. Use interfaces to abstract implementation details and dependencies.<\/p>\n<p><strong>12. Emergence<\/strong><\/p>\n<p><em>The gist<\/em>: Simple design, refactoring, and a focus on building well-crafted code lead to emergent behavior.<br \/> <em>Conceptual Example<\/em>:<br \/> Regularly refactor and simplify your code. Remove duplication, improve names, and break large functions into smaller, more focused ones.<\/p>\n<p><strong>13. Concurrency<\/strong><\/p>\n<p> <em>The gist<\/em>: Concurrency is tricky; keep it separate and well-managed.<\/p>\n<pre><code class=\"go\">func processConcurrently(data []int) {   var wg sync.WaitGroup   for _, value := range data {     wg.Add(1)     go func(val int) {       defer wg.Done()       processValue(val)     }(value)   }   wg.Wait() } <\/code><\/pre>\n<p><strong>14. Successive Refinement<\/strong><\/p>\n<p> <em>The gist<\/em>: Code should be continuously improved upon.<br \/> <em>Conceptual Example<\/em>:<br \/> Take an existing function or module and improve it: clarify names, split large functions, reduce dependencies, and add tests.<\/p>\n<p><strong>15. JUnit Internals<\/strong><\/p>\n<p> <em>The gist<\/em>: Understanding how good frameworks and libraries work can inspire you to write better code.<br \/> <em>Conceptual Example<\/em>:<br \/> Look into the source code of a well-respected Go package to understand its structure and design decisions.<\/p>\n<p><strong>16. Refactoring SerialDate<\/strong><\/p>\n<p> <em>The gist<\/em>: Refactoring is an essential tool for maintaining and improving the structure of existing code.<br \/> <em>Conceptual Example<\/em>:<br \/> Identify a complex module or function in your codebase and step through a refactoring process to improve it.<\/p>\n<p><strong>17. Smells and Heuristics<\/strong><\/p>\n<p><em>The gist<\/em>: Recognize common &#171;smells&#187; in your code that indicate problems and understand heuristics for solving them.<br \/> <em>Conceptual Example<\/em>:<br \/> Review your code for &#171;smells&#187; such as rigidity, needless complexity, and duplication. Apply heuristics like the Single Responsibility Principle and DRY (Don&#8217;t Repeat Yourself) to improve it.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>Applying clean code principles isn&#8217;t just about following rules; it&#8217;s about developing a mindset. The more you practice writing clear, concise, and maintainable code, the more natural it will become. Just making a program that works isn&#8217;t enough; it should also be tidy and understandable. Remember, clean code benefits your future self and your teammates, so always aim for clarity and simplicity. Keep it tidy!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/782920\/\"> https:\/\/habr.com\/ru\/articles\/782920\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>1. Clean Code<\/strong><\/p>\n<p><em>The gist<\/em>: Clean code is more than just working code; it&#8217;s code that other developers can easily read, understand, and modify.<\/p>\n<pre><code class=\"go\">\/\/ Not so clean func p(a []int) {   \/\/ ...some cryptic code... } \/\/ Clean func sortNumbers(numbers []int) {   \/\/ sorting logic... } <\/code><\/pre>\n<p><strong>2. Meaningful Names<\/strong><\/p>\n<p> <em>The gist<\/em>: Use descriptive and specific names that reveal your intention.<\/p>\n<pre><code class=\"go\">\/\/ Confusing var d int \/\/ elapsed time in days \/\/ Clear var elapsedTimeInDays int \/\/ Even clearer in context func calculateElapsedTime(startDate, endDate time.Time) int {   return int(endDate.Sub(startDate).Hours() \/ 24) } <\/code><\/pre>\n<p><strong>3. Functions<\/strong><\/p>\n<p> <em>The gist<\/em>: Functions should do one thing, be small, and have no side effects.<\/p>\n<pre><code class=\"go\">\/\/ Too complex func handleHttpRequest(r http.Request) { \/\/ parsing, logging, and handling... } \/\/ Decomposed into focused functions func parseRequest(r http.Request) RequestData {...} func logRequest(data RequestData) {...} func handleRequest(data RequestData) Response {...} <\/code><\/pre>\n<p><strong>4. Comments<\/strong><\/p>\n<p> <em>The gist<\/em>: Good code mostly speaks for itself.<\/p>\n<pre><code class=\"go\">\/\/ Unnecessary \/\/ Check if user is valid if user.IsValid() {...} \/\/ Clear code if user.IsValid() {...} \/\/ No comment needed <\/code><\/pre>\n<p><strong>5. Formatting<\/strong><\/p>\n<p><em>The gist<\/em>: Consistent and thoughtful formatting makes your code easier to read and understand.<\/p>\n<pre><code class=\"go\">\/\/ Inconsistent func foo() {   var x int   x=3   fmt.Println(x) } \/\/ Consistent func formatNumber(number int) string {   formatted := fmt.Sprintf(\"%03d\", number)   return formatted } <\/code><\/pre>\n<p><strong>6. Objects and Data Structures<\/strong><\/p>\n<p><em>The gist<\/em>: Objects hide their data behind abstractions and expose functions to operate on that data. Data structures expose their data and have no significant behavior.<\/p>\n<pre><code class=\"go\">\/\/ Data structure type Rectangle struct {   Width  float64   Height float64 } \/\/ Object-like behavior type Shape interface {   Area() float64 } func (r Rectangle) Area() float64 {   return r.Width * r.Height } <\/code><\/pre>\n<p><strong>7. Error Handling<\/strong><\/p>\n<p><em>The gist<\/em>: Treat error handling as a primary concern, not an afterthought.<\/p>\n<pre><code class=\"go\">func connectDatabase(connectionString string) (*sql.DB, error) {   db, err := sql.Open(\"postgres\", connectionString)   if err != nil {     return nil, fmt.Errorf(\"error connecting to database: %v\", err)   }   \/\/ Additional connection verification...   return db, nil } <\/code><\/pre>\n<p><strong>8. Boundaries<\/strong><\/p>\n<p><em>The gist<\/em>: Respect boundaries between different layers and services by keeping interchanges well-defined and clean.<\/p>\n<pre><code class=\"go\">\/\/ Interfacing with an external package func readConfigFile(path string) (Config, error) {   var config Config   data, err := ioutil.ReadFile(path)   if err != nil {     return config, err   }   err = json.Unmarshal(data, &amp;config)   return config, err } <\/code><\/pre>\n<p><strong>9. Unit Tests<\/strong><\/p>\n<p><em>The gist<\/em>: Tests keep your code flexible, maintainable, and understandable.<\/p>\n<pre><code class=\"go\">func TestCalculateTotal(t *testing.T) {   total := calculateTotal([]int{10, 20, 30})   if total != 60 {     t.Errorf(\"Expected 60, got %d\", total)   } } <\/code><\/pre>\n<p><strong>10. Classes (Structs and Interfaces in Go)<\/strong><\/p>\n<p><em>The gist<\/em>: Keep your data structures small, focused, and with a clear purpose.<\/p>\n<pre><code class=\"go\">type Server interface {   Start()   Stop() } type HttpServer struct {   \/\/ Server configuration fields } func (h *HttpServer) Start() {   \/\/ start server } func (h *HttpServer) Stop() {   \/\/ stop server } <\/code><\/pre>\n<p><strong>11. Systems<\/strong><\/p>\n<p><em>The gist<\/em>: Building clean systems involves organizing code into layers and managing dependencies carefully.<br \/> <em>Conceptual Example<\/em>:<br \/> Organize your code into packages with clear purposes. Use interfaces to abstract implementation details and dependencies.<\/p>\n<p><strong>12. Emergence<\/strong><\/p>\n<p><em>The gist<\/em>: Simple design, refactoring, and a focus on building well-crafted code lead to emergent behavior.<br \/> <em>Conceptual Example<\/em>:<br \/> Regularly refactor and simplify your code. Remove duplication, improve names, and break large functions into smaller, more focused ones.<\/p>\n<p><strong>13. Concurrency<\/strong><\/p>\n<p> <em>The gist<\/em>: Concurrency is tricky; keep it separate and well-managed.<\/p>\n<pre><code class=\"go\">func processConcurrently(data []int) {   var wg sync.WaitGroup   for _, value := range data {     wg.Add(1)     go func(val int) {       defer wg.Done()       processValue(val)     }(value)   }   wg.Wait() } <\/code><\/pre>\n<p><strong>14. Successive Refinement<\/strong><\/p>\n<p> <em>The gist<\/em>: Code should be continuously improved upon.<br \/> <em>Conceptual Example<\/em>:<br \/> Take an existing function or module and improve it: clarify names, split large functions, reduce dependencies, and add tests.<\/p>\n<p><strong>15. JUnit Internals<\/strong><\/p>\n<p> <em>The gist<\/em>: Understanding how good frameworks and libraries work can inspire you to write better code.<br \/> <em>Conceptual Example<\/em>:<br \/> Look into the source code of a well-respected Go package to understand its structure and design decisions.<\/p>\n<p><strong>16. Refactoring SerialDate<\/strong><\/p>\n<p> <em>The gist<\/em>: Refactoring is an essential tool for maintaining and improving the structure of existing code.<br \/> <em>Conceptual Example<\/em>:<br \/> Identify a complex module or function in your codebase and step through a refactoring process to improve it.<\/p>\n<p><strong>17. Smells and Heuristics<\/strong><\/p>\n<p><em>The gist<\/em>: Recognize common &#171;smells&#187; in your code that indicate problems and understand heuristics for solving them.<br \/> <em>Conceptual Example<\/em>:<br \/> Review your code for &#171;smells&#187; such as rigidity, needless complexity, and duplication. Apply heuristics like the Single Responsibility Principle and DRY (Don&#8217;t Repeat Yourself) to improve it.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>Applying clean code principles isn&#8217;t just about following rules; it&#8217;s about developing a mindset. The more you practice writing clear, concise, and maintainable code, the more natural it will become. Just making a program that works isn&#8217;t enough; it should also be tidy and understandable. Remember, clean code benefits your future self and your teammates, so always aim for clarity and simplicity. Keep it tidy!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/782920\/\"> https:\/\/habr.com\/ru\/articles\/782920\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-363878","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/363878","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=363878"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/363878\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=363878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=363878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=363878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}