11-26-2020, 12:17 AM
7 Tips to Write Clean Code
<div><p><em>This chapter draft from my upcoming book <strong>From One to Zero</strong> to appear in 2021 with NoStarch will teach you why and how to write clean and simple code. To stay tuned about the book release, sign up for the <a href="https://blog.finxter.com/email-academy/" target="_blank" rel="noreferrer noopener" title="Email Academy">Finxter email coding acadamy</a> (it’s free)! </em></p>
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="7 Tips to Clean Code" width="1400" height="788" src="https://www.youtube.com/embed/x2IuGDMqBSU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<hr class="wp-block-separator"/>
<h2>Write Clean & Simple Code</h2>
<p><strong>Story</strong>: I learned to focus on writing clean code the hard way. One of my research projects during my time as a doctoral researcher in distributed systems was to code a distributed graph processing system from scratch. The system allowed you to run graph algorithms such as computing the shortest path on a large map in a distributed environment to speed up computation among multiple machines. If you’ve ever written a distributed application where two processes that reside on different computers interact with each other via messages, you know that the complexity can quickly become overwhelming. My code had thousands of lines of code and bugs were popping up frequently. I didn’t make any progress for weeks at a time—it was very frustrating. In theory, the concepts I developed sounded great and convincing. But practice got me! Finally, after a month or so working full-time on the code base without seeing any encouraging progress, I decided to radically simplify the code base. I started to use libraries instead of coding functions myself. I removed large code blocks of premature optimizations (see later). I removed code blocks that I had commented out for a possible later use. I refactored variable and function names. I structured the code in logical units and classes. And, after a week or so, not only was my code more readable and understandable by other researchers, it was also more efficient and less buggy. I managed to make progress again and my frustration quickly morphed into enthusiasm—clean code had rescued my research project!</p>
<p><strong>Complexity</strong>: In the previous chapters, you’ve learned how harmful complexity is for any code project in the real world. Complexity kills your productivity, motivation, and time. Because most of us haven’t learned to speak in source code from an early age, it can quickly overwhelm our cognitive abilities. The more code you have, the more overwhelming it becomes. But even short code snippets and algorithms can be complicated. The following one-liner code snippet from our book <em><a href="https://amzn.to/2WAYeJE" target="_blank" rel="noreferrer noopener" title="https://amzn.to/2WAYeJE">Python One-Liners</a></em> is a great example of a piece of source code that is short and concise, but still complex!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Quicksort algorithm to sort a list of integers
unsorted = [33, 2, 3, 45, 6, 54, 33] q = lambda l: q([x for x in l[1:] if x <= l[0]]) + [l[0]] + q([x for x in l if x > l[0]]) if l else [] print(q(unsorted))
# [2, 3, 6, 33, 33, 45, 54]
</pre>
<p>You can find an explanation of this code snippet in our book <em><strong><a href="https://pythononeliners.com/" target="_blank" rel="noreferrer noopener" title="https://pythononeliners.com/">Python One-Liners</a></strong></em> or online at <a href="https://blog.finxter.com/python-one-line-quicksort/">https://blog.finxter.com/python-one-line-quicksort/</a>.</p>
<p>Complexity comes from many directions when working with source code. It slows down our understanding of the code. And it increases the number of bugs in our code. Both slow understanding and more bugs increase the project costs and the number of people hours required to finish it. Robert C. Martin, author of the book <em>Clean Code</em>, argues that the more difficult it is to read and understand code, the higher the costs to write code as well:</p>
<p class="has-luminous-vivid-amber-background-color has-background"><em>“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”</em> — <strong>Robert C. Martin</strong></p>
<p>This relationship is visualized in <strong>Figure 5-1</strong>. The x axis corresponds to the number of lines written in a given code project. The y axis corresponds to the time to write one additional line of code. In general, the more code you’ve already written in one project, the more time it takes to write an additional line of code. Why is that? Say, you’ve written n lines of code and you add the <code>n+1</code><sup>st</sup> line of code. Adding this line may have an effect on potentially all previously written lines. It may have a small performance penalty which impacts the overall project. It may use a variable that is defined at another place. It may introduce a bug (with probability <em>c</em>) and to find that bug, you must search the whole project (so, your expected costs per line of code is <em>c * T(n)</em> for a steadily increasing function <em>T</em> with increasing input <em>n</em>). It may force you to write additional lines of code to ensure backward compatibility. There are many more reasons but you get the point: the additional complexity causes to slow down your progress the more code you’ve written.</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="604" height="340" src="https://blog.finxter.com/wp-content/uploads/2020/11/image-46.png" alt="Quick & Dirty Code vs Clean Code" class="wp-image-17319" srcset="https://blog.finxter.com/wp-content/uploads/2020/11/image-46.png 604w, https://blog.finxter.com/wp-content/uplo...00x169.png 300w, https://blog.finxter.com/wp-content/uplo...150x84.png 150w" sizes="(max-width: 604px) 100vw, 604px" /></figure>
<p><em><strong>Figure 5-1:</strong> Clean code improves scalability and maintainability of your code base.</em></p>
<p>But Figure 5-1 also shows the difference between writing dirty versus clean code. If writing dirty code wouldn’t result in any benefit, nobody would do it! There’s a very real benefit of writing dirty code: it’s less time consuming in the short-term and for small code projects. If you cram all the functionality in a 100-line code script, you don’t need to invest a lot of time thinking and structuring your project. But as you add more and more code, the monolithic code file grows from 100 to 1000 lines and at a certain point, it’ll be much less efficient compared to a more thoughtful approach where you structure the code logically in different modules, classes, or files. As a rule of thumb: try to always write thoughtful and clean code—because the additional costs for thinking, refactoring, and restructuring will pay back many times over for any non-trivial project. Besides—writing clean code is just the right thing to do. The philosophy of carefully crafting your programming art will carry you further in life.</p>
<p>You don’t always know the second-order consequences of your code. Think of the spacecraft on a mission towards Venus in 1962 where a tiny bug—an omission of a hyphen in the source code—caused NASA engineers to issue a self-destruct command which resulted in a loss of the rocket worth more than $18 million at the time.</p>
<p>To mitigate all of those problems, there’s a simple solution: write simpler code. Simple code is less error-prone, less crowded, easier to grasp, and easier to maintain. It is more fun to read and write. In many cases, it’s more efficient and takes less space. It also facilitates scaling your project because people won’t be scared off by the complexity of the project. If new coders peek in your code project to see whether they want to contribute, they better believe that they can understand it. With simple code, everything in your project will get simpler. You’ll make faster progress, get more support, spend less time debugging, be more motivated, and have more fun in the process.</p>
<p><strong><em>So, let’s learn how to write clean and simple code, shall we?</em></strong></p>
<p>Clean code is elegant and pleasing to read. It is focused in the sense that each function, class, module focuses on one idea. A function <code>transfer_funds(A,B)</code> in your banking application does just that—transferring funds from account <code>A</code> to account <code>B</code>. It doesn’t check the credit of the sender <code>A</code> —for this, there’s another function <code>check_credit(A)</code>. Simple but easy to understand and focused. How do you get simple and clean code? By spending time and effort to edit and revise the code. This is called refactoring and it must be a scheduled and crucial element of your software development process.</p>
<p>Let’s dive into some principles to write clean code. Revisit them from time to time—they’ll become meaningful sooner or later if you’re involved in some real-world projects.</p>
<h2>Principles to Write Clean Code</h2>
<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" width="853" height="480" src="https://blog.finxter.com/wp-content/uploads/2020/11/7-Tips-to-Clean-Code-1.gif" alt="7 Tips to Write Clean Code" class="wp-image-17342"/></figure>
</div>
<p>Next, you’ll going to learn a number of principles that’ll help you write cleaner code.</p>
<h3>Principle 1: You Ain’t Going to Need It</h3>
<p>The principle suggests that you should never implement code if you only expect that you’re going to need its provided functionality someday in the future—because you ain’t gonna need it! Instead, write code only if you’re 100% sure that you need it. Code for today’s needs and not tomorrow’s.</p>
<p>It helps to think from first principles: The simplest and cleanest code is the empty file. It doesn’t have any bug and it’s easy to understand. Now, go from there—what do you need to add to that? In Chapter 4, you’ve learned about the minimum viable product. If you minimize the number of features you pursue, you’ll harvest cleaner and simpler code than you could ever attain through refactoring methods or all other principles combined. As you know by now, leaving out features is not only useful if they’re unnecessary. Leaving them out even makes sense if they provide relatively little value compared to other features you could implement instead. Opportunity costs are seldomly measured but most often they are very significant. Only because a feature provides some benefits doesn’t justify its implementation. You have to really need the feature before you even consider implementing it. Reap the low-hanging fruits first before you reach higher!</p>
<h3>Principle 2: The Principle of Least Surprise</h3>
<p>This principle is one of the golden rules of effective application and user experience design. If you open the Google search engine, the cursor will be already focused in the search input field so that you can start typing your search keyword right away without needing to click into the input field. Not surprising at all—but a great example of the principle of least surprise. Clean code also leverages this design principle. Say, you write a currency converter that converts the user’s input from USD to RMB. You store the user input in a variable. Which variable name is better suited, <code>user_input</code> or <code>var_x</code>? The principle of least surprise answers this question for you!</p>
<h3>Principle 3: Don’t Repeat Yourself</h3>
<p>Don’t Repeat Yourself (DRY) is a widely recognized principle that implies that if you write code that partially repeats itself—or that’s even copy&pasted from your own code—is a sign of bad coding style. A negative example is the following Python code that prints the same string five times to the shell:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">print('hello world')
print('hello world')
print('hello world')
print('hello world')
print('hello world')</pre>
<p>The code repeats itself so the principle suggests that there will be a better way of writing it. And there is!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">for i in range(5): print('hello world')
</pre>
<p>The code is much shorter but semantically equivalent. There’s no redundancy in the code.</p>
<p>The principle also shows you when to create a function and when it isn’t required to do so. Say, you need to convert miles into kilometers in multiple instances in your code (see <strong>Listing 5-1</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">miles = 100
kilometers = miles * 1.60934 # ... # BAD EXAMPLE
distance = 20 * 1.60934 # ... print(kilometers)
print(distance) '''
OUTPUT:
160.934
32.1868 '''
</pre>
<p><em><strong>Listing 5-1:</strong> Convert miles to kilometers twice.</em></p>
<p>The principle <strong><em>Don’t Repeat Yourself</em></strong> suggests that it would be better to write a function <code>miles_to_km(miles)</code> once—rather than performing the same conversion explicitly in the code multiple times (see <strong>Listing 5-2</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def miles_to_km(miles): return miles * 1.60934 miles = 100
kilometers = miles_to_km(miles) # ... distance = miles_to_km(20) # ... print(kilometers)
print(distance) '''
OUTPUT:
160.934
32.1868 '''
</pre>
<p><em><strong>Listing 5-2: </strong>Using a function to convert miles to kilometers.</em></p>
<p>This way, the code is easier to maintain, you can easily increase the precision of the conversion afterwards without searching the code for all instances where you used the imprecise conversion methodology. Also, it’s easier to understand for human readers of your code. There’s no doubt about the purpose of the function <code>miles_to_km(20)</code> while you may have to think harder about the purpose of the computation 20 * 1.60934.</p>
<p>The principle <strong><em>Don’t Repeat Yourself</em></strong> is often abbreviated as DRY and violations of it as WET: <strong><em>We Enjoy Typing</em></strong>, <strong><em>Write Everything Twice</em></strong>, and <strong><em>Waste Everyone’s Time</em></strong>.</p>
<h3>Principle 4: Code For People Not Machines</h3>
<p>The main purpose of source code is to define what machines should do and how to do it. Yet, if this was the only criteria, you’d use a low-level machine language such as assembler to accomplish this goal because it’s the most expressive and most powerful language. The purpose of high-level programming languages such as Python is to help people write better code and do it more quickly. Our next principle for clean code is to constantly remind yourself that you’re writing code for other people and not for machines. If your code will have any impact in the real world, it’ll be read multiple times by you or a programmer that takes your place if you stop working on the code base. Always assume that your source code will be read by other people. What can you do to make their job easier? Or, to put it more plainly: what can you do to mitigate the negative emotions they’ll experience against the original programmer of the code base their working on? Code for people not machines!</p>
<p>What does this mean in practice? There are many implications. First of all, use meaningful variable names.<strong> Listing 5-3</strong> shows a negative example without meaningful variable names.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># BAD
xxx = 10000
yyy = 0.1
zzz = 10 for iii in range(zzz): print(xxx * (1 + yyy)**iii)
</pre>
<p><em><strong>Listing 5-3:</strong> Example of writing code for machines.</em></p>
<p>Take a guess: what does the code compute?</p>
<p>Let’s have a look at the semantically equivalent code in <strong>Listing 5-4</strong> that uses meaningful variable names.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># GOOD
investments = 10000
yearly_return = 0.1
years = 10 for year in range(years): print(investments * (1 + yearly_return)**year)
</pre>
<p><em><strong>Listing 5-4:</strong> Using a function to convert miles to kilometers.</em></p>
<p>The variable names indicate that you calculate the value of an initial investment of 1000 compounded over 10 years assuming an annual return of 10%.</p>
<p>The principle to write code has many more applications. It also applies to indentations, whitespaces, comments, and line lengths. Clean code radically optimizes for human readability. As Martin Fowler, international expert on software engineering and author of the popular book Refactoring, argues:</p>
<p class="has-luminous-vivid-amber-background-color has-background"><em><strong>“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”</strong></em></p>
<h3>Principle 5: Stand on the Shoulders of Giants</h3>
<p>There’s no value in reinventing the wheel. Programming is a decade-old industry and the best coders in the world have given us a great legacy: a collective database of millions of fine-tuned and well-tested algorithms and code functions. Accessing the collective wisdom of millions of programmers is as simple as using a one-liner import statement. You’d be crazy not to use this superpower in your own projects. Besides being easy to use, using library code is likely to improve the efficiency of your code because functions that have been used by thousands of coders tend to be much more optimized than your own code functions. Furthermore, library calls are easier to understand and take less space in your code project. For example, if you’d need a clustering algorithm to visualize clusters of customers, you can either implement it yourself or stand on the shoulders of giants and import a clustering algorithm from an external library and pass your data into it. The latter is far more time efficient—you’ll take much less time to implement the same functionality with fewer bugs, less space, and more performant code. Libraries are one of the top reasons why master coders can be 10,000 times more productive than average coders.</p>
<p>Here’s the two-liner that imports the <a href="https://blog.finxter.com/tutorial-how-to-run-k-means-clustering-in-1-line-of-python/" target="_blank" rel="noreferrer noopener" title="[Tutorial] How to Run K-Means Clustering in 1 Line of Python?">KMeans </a>module from the scikit-learn Python library rather than reinventing the wheel:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
</pre>
<p>If you’d want to implement the KMeans algorithm, it’ll take you a few hours and 50 lines of code—and it’ll clutter your code base so that all future code will become harder to implement.</p>
<h3>Principle 6: Use the Right Names</h3>
<p>Your decisions on how to name your functions, function arguments, objects, methods, and variables uncovers whether you’re a beginner, intermediate, or expert coder. How? In any programming language, there are many naming conventions that are used by all experienced coders. If you violate them, it immediately tells the reader of your code base that you’ve not had a lot of experience with practical code projects. The more such “tells” exist in your code, the less serious will a reader of your code take it.</p>
<p>There are a lot of explicit and implicit rules governing the correct naming of your code elements. These rules may even differ from programming language to programming language. For example, you’ll use <code>camelCaseNaming</code> for variables in the Java programming language while you’ll use <code>underscore_naming</code> in Python. If you start using camel case in Python, everyone will immediately see that you’re a Python beginner. While you may not like this, it’s not really a big problem to be perceived as a beginner—everyone has been one at one point in time. Far worse is that other coders will be negatively surprised when reading their code. Instead of thinking about what the code does, they start thinking about how your code is written. You know the principle of least surprise—there’s no value in surprising other coders by choosing unconventional variable names. </p>
<p>So, let’s dive into a list of naming rule of thumbs you can consider when writing source code. This will speed up your ability to learn how to write clean code names. However, the best way to learn is to study the code of people who are better than you. Read a lot of programming tutorials, join the StackOverview community, and check out the Github code of open-source projects.</p>
<ul>
<li><strong>Choose descriptive names.</strong> Say you create a function to convert currencies from USD to EUR in Python. Call it <code>usd_to_eur(amount)</code> rather than <code>f(x)</code>.</li>
<li><strong>Choose unambiguous names.</strong> You may think that <code>dollar_to_euro(amount)</code> would be good name as well for the previously discussed function. While it is better than <code>f(x)</code>, it’s worse than <code>usd_to_eur(amount)</code> because it introduces an unnecessary degree of ambiguity. Do you mean US, Canadian, or Australian Dollar? If you’re in the US, the answer may be obvious to you. But an Australian coder may not know that the code is written in the US and may assume a different output. Minimize these confusions!</li>
<li><strong>Use Pronounceable Names.</strong> Most coders subconsciously read code by pronouncing it in their mind. If they cannot do this subconsciously because a variable name is unpronounceable, the problem of deciphering the variable name takes their precious attention. They have to actively think about possible ways to resolve the unexpected naming. For example, the variable name <code>cstmr_lst</code> may be descriptive and unambiguous, but it’s not pronounceable. Choosing the variable name <code>customer_list</code> is well worth the additional space in your code!</li>
<li><strong>Use Named Constants, Not Magic Numbers</strong>. In your code, you may use the magic number 0.9 multiple times as a factor to convert a sum in USD to a sum in EUR. However, the reader of your code—including your future self that rereads your own code—has to think about the purpose of this number. It’s not self-explanatory. A far better way of handling this “magic number” 0.9 is to store it in a variable <code>CONVERSION_RATE = 0.9</code> and use it as a factor in your conversion computations. For example, you may then calculate your income in EUR as <code>income_euro = CONVERSION_RATE * income_usd</code>. This way, their’s no magic number in your code and it becomes more readable.</li>
</ul>
<p>These are only some of the naming conventions. Again, to pick the conventions up, it’s best to Google them once (for example, “Python Naming Conventions”) and study Github code projects from experts in your field.</p>
<h3>Principle 7: Single-Responsibility Principle</h3>
<p>The single responsibility principle means that every function has one main task. A function should be small and do only one thing. It is better to have many small functions than one big function doing everything at the same time. The reason is simple: the encapsulation of functionality reduces overall complexity in your code. </p>
<p>As a rule of thumb: <strong><em>every class and every function should have only one reason to change.</em></strong> If there are multiple reasons to change, multiple programmers would like to change the same class at the same time. You’ve mixed too many responsibility in your class and now it becomes messy and cluttered.</p>
<p>Let’s consider a small examples using Python code that may run on an ebook reader to model and manage the reading experience of a user (see <strong>Listing 5-5</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Book: def __init__(self): self.title = "Python One-Liners" self.publisher = "NoStarch" self.author = "Mayer" self.current_page = 0 def get_title(self): return self.title def get_author(self): return self.author def get_publisher(self): return self.publisher def next_page(self): self.current_page += 1 return self.current_page def print_page(self): print(f"... Page Content {self.current_page} ...") python_one_liners = Book() print(python_one_liners.get_publisher())
# NoStarch python_one_liners.print_page()
# ... Page Content 0 ... python_one_liners.next_page()
python_one_liners.print_page()
# ... Page Content 1 ...
</pre>
<p><em><strong>Listing 5-5:</strong> Modeling the book class with violation of the single responsibility principle—the book class is responsible for both data modeling and data representation. It has two responsibilities.</em></p>
<p>The code in <strong>Listing 5-5</strong> defines a class <code>Book</code> with four attributes: title, author, publisher, and current page number. You define getter methods for the attributes, as well as some minimal functionality to move to the next page. The function <code>next_page()</code> may be called each time the user presses a button on the reading device. Another function <code>print_page()</code> is responsible for printing the current page to the reading device. This is only given as a stub and it’ll be more complicated in the real world. While the code looks clean and simple, it violates the single responsibility principle: the class Book is responsible for modeling the data such as the book content, but it is also responsible for printing the book to the device. You have multiple reasons to change. You may want to change the modeling of the book’s data—for example, using a database instead of a file-based input/output method. But you may also want to change the representation of the modeled data—for example, using another book formatting scheme on other type of screens. Modeling and printing are two different functions encapsulated in a single class. Let’s change this in<strong> Listing 5-6</strong>!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Book: def __init__(self): self.title = "Python One-Liners" self.publisher = "NoStarch" self.author = "Mayer" self.current_page = 0 def get_title(self): return self.title def get_author(self): return self.author def get_publisher(self): return self.publisher def get_page(self): return self.current_page def next_page(self): self.current_page += 1 class Printer: def print_page(self, book): print(f"... Page Content {book.get_page()} ...") python_one_liners = Book()
printer = Printer() printer.print_page(python_one_liners)
# ... Page Content 0 ... python_one_liners.next_page()
printer.print_page(python_one_liners)
# ... Page Content 1 ...
</pre>
<p><em><strong>Listing 5-6:</strong> Adhering to the single responsibility principle—the book class is responsible for data modeling and the printing class is responsible for data representation.</em></p>
<p>The code in <strong>Listing 5-6</strong> accomplishes the same task but it satisfies the single responsibility principle. You create both a book and a printer class. The book class represents book meta information and the current page number. The printer class prints the book to the device. You pass the book for which you want to print the current page into the method <code>Printer.print_page()</code>. This way, data modeling and data representation are decoupled and the code becomes easier to maintain.</p>
<hr class="wp-block-separator"/>
<p>Do you want to develop the skills of a <strong>well-rounded Python professional</strong>—while getting paid in the process? Become a Python freelancer and order your book <a href="https://amzn.to/2Re2JqO" target="_blank" rel="noreferrer noopener"><strong>Leaving the Rat Race with Python</strong></a> on Amazon (<em>Kindle/Print</em>)!</p>
<div class="wp-block-image">
<figure class="aligncenter size-medium is-resized"><a href="https://amzn.to/2Re2JqO" target="_blank" rel="noopener noreferrer"><img loading="lazy" src="https://blog.finxter.com/wp-content/uploads/2020/08/final_cover-200x300.jpg" alt="Leaving the Rat Race with Python Book" class="wp-image-11850" width="200" height="300" srcset="https://blog.finxter.com/wp-content/uploads/2020/08/final_cover-200x300.jpg 200w, https://blog.finxter.com/wp-content/uplo...scaled.jpg 683w, https://blog.finxter.com/wp-content/uplo...8x1152.jpg 768w, https://blog.finxter.com/wp-content/uplo...4x1536.jpg 1024w, https://blog.finxter.com/wp-content/uplo...5x2048.jpg 1365w, https://blog.finxter.com/wp-content/uplo...50x225.jpg 150w" sizes="(max-width: 200px) 100vw, 200px" /></a></figure>
</div>
<h2>References:</h2>
<ul>
<li><a href="https://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle--net-36074" target="_blank" rel="noreferrer noopener">https://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle–net-36074 </a></li>
<li><a href="https://en.wikipedia.org/wiki/Single-responsibility_principle" target="_blank" rel="noreferrer noopener">https://en.wikipedia.org/wiki/Single-responsibility_principle</a></li>
<li><a href="https://medium.com/hackernoon/the-secret-behind-the-single-responsibility-principle-e2f3692bae25" target="_blank" rel="noreferrer noopener">https://medium.com/hackernoon/the-secret-behind-the-single-responsibility-principle-e2f3692bae25</a></li>
<li><a href="https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8263157&casa_token=Ydc5j4wwdWAAAAAA:iywl9VJ_TRe_Q3x2F7-XOgKHvrnz7TuJhBQ8iDtsSVDv1WXTGN-bCSscP0WjSs7X7LVXJFGNfgM&tag=1" target="_blank" rel="noreferrer noopener">https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8263157&casa_token=Ydc5j4wwdWAAAAAA:iywl9VJ_TRe_Q3x2F7-XOgKHvrnz7TuJhBQ8iDtsSVDv1WXTGN-bCSscP0WjSs7X7LVXJFGNfgM&tag=1</a></li>
<li><a href="https://raygun.com/blog/costly-software-errors-history/" target="_blank" rel="noreferrer noopener">https://raygun.com/blog/costly-software-errors-history/</a></li>
</ul>
<h2>Where to Go From Here?</h2>
<p>Enough theory, let’s get some practice!</p>
<p>To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?</p>
<p><strong>Practice projects is how you sharpen your saw in coding!</strong></p>
<p>Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?</p>
<p>Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.</p>
<p>Join my free webinar <a rel="noreferrer noopener" href="https://blog.finxter.com/webinar-freelancer/" target="_blank">“How to Build Your High-Income Skill Python”</a> and watch how I grew my coding business online and how you can, too—from the comfort of your own home.</p>
<p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">Join the free webinar now!</a></p>
<p>The post <a href="https://blog.finxter.com/tips-to-write-clean-code/" target="_blank" rel="noopener noreferrer">7 Tips to Write Clean Code</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>
https://www.sickgaming.net/blog/2020/11/...lean-code/
<div><p><em>This chapter draft from my upcoming book <strong>From One to Zero</strong> to appear in 2021 with NoStarch will teach you why and how to write clean and simple code. To stay tuned about the book release, sign up for the <a href="https://blog.finxter.com/email-academy/" target="_blank" rel="noreferrer noopener" title="Email Academy">Finxter email coding acadamy</a> (it’s free)! </em></p>
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="7 Tips to Clean Code" width="1400" height="788" src="https://www.youtube.com/embed/x2IuGDMqBSU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<hr class="wp-block-separator"/>
<h2>Write Clean & Simple Code</h2>
<p><strong>Story</strong>: I learned to focus on writing clean code the hard way. One of my research projects during my time as a doctoral researcher in distributed systems was to code a distributed graph processing system from scratch. The system allowed you to run graph algorithms such as computing the shortest path on a large map in a distributed environment to speed up computation among multiple machines. If you’ve ever written a distributed application where two processes that reside on different computers interact with each other via messages, you know that the complexity can quickly become overwhelming. My code had thousands of lines of code and bugs were popping up frequently. I didn’t make any progress for weeks at a time—it was very frustrating. In theory, the concepts I developed sounded great and convincing. But practice got me! Finally, after a month or so working full-time on the code base without seeing any encouraging progress, I decided to radically simplify the code base. I started to use libraries instead of coding functions myself. I removed large code blocks of premature optimizations (see later). I removed code blocks that I had commented out for a possible later use. I refactored variable and function names. I structured the code in logical units and classes. And, after a week or so, not only was my code more readable and understandable by other researchers, it was also more efficient and less buggy. I managed to make progress again and my frustration quickly morphed into enthusiasm—clean code had rescued my research project!</p>
<p><strong>Complexity</strong>: In the previous chapters, you’ve learned how harmful complexity is for any code project in the real world. Complexity kills your productivity, motivation, and time. Because most of us haven’t learned to speak in source code from an early age, it can quickly overwhelm our cognitive abilities. The more code you have, the more overwhelming it becomes. But even short code snippets and algorithms can be complicated. The following one-liner code snippet from our book <em><a href="https://amzn.to/2WAYeJE" target="_blank" rel="noreferrer noopener" title="https://amzn.to/2WAYeJE">Python One-Liners</a></em> is a great example of a piece of source code that is short and concise, but still complex!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Quicksort algorithm to sort a list of integers
unsorted = [33, 2, 3, 45, 6, 54, 33] q = lambda l: q([x for x in l[1:] if x <= l[0]]) + [l[0]] + q([x for x in l if x > l[0]]) if l else [] print(q(unsorted))
# [2, 3, 6, 33, 33, 45, 54]
</pre>
<p>You can find an explanation of this code snippet in our book <em><strong><a href="https://pythononeliners.com/" target="_blank" rel="noreferrer noopener" title="https://pythononeliners.com/">Python One-Liners</a></strong></em> or online at <a href="https://blog.finxter.com/python-one-line-quicksort/">https://blog.finxter.com/python-one-line-quicksort/</a>.</p>
<p>Complexity comes from many directions when working with source code. It slows down our understanding of the code. And it increases the number of bugs in our code. Both slow understanding and more bugs increase the project costs and the number of people hours required to finish it. Robert C. Martin, author of the book <em>Clean Code</em>, argues that the more difficult it is to read and understand code, the higher the costs to write code as well:</p>
<p class="has-luminous-vivid-amber-background-color has-background"><em>“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”</em> — <strong>Robert C. Martin</strong></p>
<p>This relationship is visualized in <strong>Figure 5-1</strong>. The x axis corresponds to the number of lines written in a given code project. The y axis corresponds to the time to write one additional line of code. In general, the more code you’ve already written in one project, the more time it takes to write an additional line of code. Why is that? Say, you’ve written n lines of code and you add the <code>n+1</code><sup>st</sup> line of code. Adding this line may have an effect on potentially all previously written lines. It may have a small performance penalty which impacts the overall project. It may use a variable that is defined at another place. It may introduce a bug (with probability <em>c</em>) and to find that bug, you must search the whole project (so, your expected costs per line of code is <em>c * T(n)</em> for a steadily increasing function <em>T</em> with increasing input <em>n</em>). It may force you to write additional lines of code to ensure backward compatibility. There are many more reasons but you get the point: the additional complexity causes to slow down your progress the more code you’ve written.</p>
<figure class="wp-block-image size-large"><img loading="lazy" width="604" height="340" src="https://blog.finxter.com/wp-content/uploads/2020/11/image-46.png" alt="Quick & Dirty Code vs Clean Code" class="wp-image-17319" srcset="https://blog.finxter.com/wp-content/uploads/2020/11/image-46.png 604w, https://blog.finxter.com/wp-content/uplo...00x169.png 300w, https://blog.finxter.com/wp-content/uplo...150x84.png 150w" sizes="(max-width: 604px) 100vw, 604px" /></figure>
<p><em><strong>Figure 5-1:</strong> Clean code improves scalability and maintainability of your code base.</em></p>
<p>But Figure 5-1 also shows the difference between writing dirty versus clean code. If writing dirty code wouldn’t result in any benefit, nobody would do it! There’s a very real benefit of writing dirty code: it’s less time consuming in the short-term and for small code projects. If you cram all the functionality in a 100-line code script, you don’t need to invest a lot of time thinking and structuring your project. But as you add more and more code, the monolithic code file grows from 100 to 1000 lines and at a certain point, it’ll be much less efficient compared to a more thoughtful approach where you structure the code logically in different modules, classes, or files. As a rule of thumb: try to always write thoughtful and clean code—because the additional costs for thinking, refactoring, and restructuring will pay back many times over for any non-trivial project. Besides—writing clean code is just the right thing to do. The philosophy of carefully crafting your programming art will carry you further in life.</p>
<p>You don’t always know the second-order consequences of your code. Think of the spacecraft on a mission towards Venus in 1962 where a tiny bug—an omission of a hyphen in the source code—caused NASA engineers to issue a self-destruct command which resulted in a loss of the rocket worth more than $18 million at the time.</p>
<p>To mitigate all of those problems, there’s a simple solution: write simpler code. Simple code is less error-prone, less crowded, easier to grasp, and easier to maintain. It is more fun to read and write. In many cases, it’s more efficient and takes less space. It also facilitates scaling your project because people won’t be scared off by the complexity of the project. If new coders peek in your code project to see whether they want to contribute, they better believe that they can understand it. With simple code, everything in your project will get simpler. You’ll make faster progress, get more support, spend less time debugging, be more motivated, and have more fun in the process.</p>
<p><strong><em>So, let’s learn how to write clean and simple code, shall we?</em></strong></p>
<p>Clean code is elegant and pleasing to read. It is focused in the sense that each function, class, module focuses on one idea. A function <code>transfer_funds(A,B)</code> in your banking application does just that—transferring funds from account <code>A</code> to account <code>B</code>. It doesn’t check the credit of the sender <code>A</code> —for this, there’s another function <code>check_credit(A)</code>. Simple but easy to understand and focused. How do you get simple and clean code? By spending time and effort to edit and revise the code. This is called refactoring and it must be a scheduled and crucial element of your software development process.</p>
<p>Let’s dive into some principles to write clean code. Revisit them from time to time—they’ll become meaningful sooner or later if you’re involved in some real-world projects.</p>
<h2>Principles to Write Clean Code</h2>
<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" width="853" height="480" src="https://blog.finxter.com/wp-content/uploads/2020/11/7-Tips-to-Clean-Code-1.gif" alt="7 Tips to Write Clean Code" class="wp-image-17342"/></figure>
</div>
<p>Next, you’ll going to learn a number of principles that’ll help you write cleaner code.</p>
<h3>Principle 1: You Ain’t Going to Need It</h3>
<p>The principle suggests that you should never implement code if you only expect that you’re going to need its provided functionality someday in the future—because you ain’t gonna need it! Instead, write code only if you’re 100% sure that you need it. Code for today’s needs and not tomorrow’s.</p>
<p>It helps to think from first principles: The simplest and cleanest code is the empty file. It doesn’t have any bug and it’s easy to understand. Now, go from there—what do you need to add to that? In Chapter 4, you’ve learned about the minimum viable product. If you minimize the number of features you pursue, you’ll harvest cleaner and simpler code than you could ever attain through refactoring methods or all other principles combined. As you know by now, leaving out features is not only useful if they’re unnecessary. Leaving them out even makes sense if they provide relatively little value compared to other features you could implement instead. Opportunity costs are seldomly measured but most often they are very significant. Only because a feature provides some benefits doesn’t justify its implementation. You have to really need the feature before you even consider implementing it. Reap the low-hanging fruits first before you reach higher!</p>
<h3>Principle 2: The Principle of Least Surprise</h3>
<p>This principle is one of the golden rules of effective application and user experience design. If you open the Google search engine, the cursor will be already focused in the search input field so that you can start typing your search keyword right away without needing to click into the input field. Not surprising at all—but a great example of the principle of least surprise. Clean code also leverages this design principle. Say, you write a currency converter that converts the user’s input from USD to RMB. You store the user input in a variable. Which variable name is better suited, <code>user_input</code> or <code>var_x</code>? The principle of least surprise answers this question for you!</p>
<h3>Principle 3: Don’t Repeat Yourself</h3>
<p>Don’t Repeat Yourself (DRY) is a widely recognized principle that implies that if you write code that partially repeats itself—or that’s even copy&pasted from your own code—is a sign of bad coding style. A negative example is the following Python code that prints the same string five times to the shell:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">print('hello world')
print('hello world')
print('hello world')
print('hello world')
print('hello world')</pre>
<p>The code repeats itself so the principle suggests that there will be a better way of writing it. And there is!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">for i in range(5): print('hello world')
</pre>
<p>The code is much shorter but semantically equivalent. There’s no redundancy in the code.</p>
<p>The principle also shows you when to create a function and when it isn’t required to do so. Say, you need to convert miles into kilometers in multiple instances in your code (see <strong>Listing 5-1</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">miles = 100
kilometers = miles * 1.60934 # ... # BAD EXAMPLE
distance = 20 * 1.60934 # ... print(kilometers)
print(distance) '''
OUTPUT:
160.934
32.1868 '''
</pre>
<p><em><strong>Listing 5-1:</strong> Convert miles to kilometers twice.</em></p>
<p>The principle <strong><em>Don’t Repeat Yourself</em></strong> suggests that it would be better to write a function <code>miles_to_km(miles)</code> once—rather than performing the same conversion explicitly in the code multiple times (see <strong>Listing 5-2</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def miles_to_km(miles): return miles * 1.60934 miles = 100
kilometers = miles_to_km(miles) # ... distance = miles_to_km(20) # ... print(kilometers)
print(distance) '''
OUTPUT:
160.934
32.1868 '''
</pre>
<p><em><strong>Listing 5-2: </strong>Using a function to convert miles to kilometers.</em></p>
<p>This way, the code is easier to maintain, you can easily increase the precision of the conversion afterwards without searching the code for all instances where you used the imprecise conversion methodology. Also, it’s easier to understand for human readers of your code. There’s no doubt about the purpose of the function <code>miles_to_km(20)</code> while you may have to think harder about the purpose of the computation 20 * 1.60934.</p>
<p>The principle <strong><em>Don’t Repeat Yourself</em></strong> is often abbreviated as DRY and violations of it as WET: <strong><em>We Enjoy Typing</em></strong>, <strong><em>Write Everything Twice</em></strong>, and <strong><em>Waste Everyone’s Time</em></strong>.</p>
<h3>Principle 4: Code For People Not Machines</h3>
<p>The main purpose of source code is to define what machines should do and how to do it. Yet, if this was the only criteria, you’d use a low-level machine language such as assembler to accomplish this goal because it’s the most expressive and most powerful language. The purpose of high-level programming languages such as Python is to help people write better code and do it more quickly. Our next principle for clean code is to constantly remind yourself that you’re writing code for other people and not for machines. If your code will have any impact in the real world, it’ll be read multiple times by you or a programmer that takes your place if you stop working on the code base. Always assume that your source code will be read by other people. What can you do to make their job easier? Or, to put it more plainly: what can you do to mitigate the negative emotions they’ll experience against the original programmer of the code base their working on? Code for people not machines!</p>
<p>What does this mean in practice? There are many implications. First of all, use meaningful variable names.<strong> Listing 5-3</strong> shows a negative example without meaningful variable names.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># BAD
xxx = 10000
yyy = 0.1
zzz = 10 for iii in range(zzz): print(xxx * (1 + yyy)**iii)
</pre>
<p><em><strong>Listing 5-3:</strong> Example of writing code for machines.</em></p>
<p>Take a guess: what does the code compute?</p>
<p>Let’s have a look at the semantically equivalent code in <strong>Listing 5-4</strong> that uses meaningful variable names.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># GOOD
investments = 10000
yearly_return = 0.1
years = 10 for year in range(years): print(investments * (1 + yearly_return)**year)
</pre>
<p><em><strong>Listing 5-4:</strong> Using a function to convert miles to kilometers.</em></p>
<p>The variable names indicate that you calculate the value of an initial investment of 1000 compounded over 10 years assuming an annual return of 10%.</p>
<p>The principle to write code has many more applications. It also applies to indentations, whitespaces, comments, and line lengths. Clean code radically optimizes for human readability. As Martin Fowler, international expert on software engineering and author of the popular book Refactoring, argues:</p>
<p class="has-luminous-vivid-amber-background-color has-background"><em><strong>“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”</strong></em></p>
<h3>Principle 5: Stand on the Shoulders of Giants</h3>
<p>There’s no value in reinventing the wheel. Programming is a decade-old industry and the best coders in the world have given us a great legacy: a collective database of millions of fine-tuned and well-tested algorithms and code functions. Accessing the collective wisdom of millions of programmers is as simple as using a one-liner import statement. You’d be crazy not to use this superpower in your own projects. Besides being easy to use, using library code is likely to improve the efficiency of your code because functions that have been used by thousands of coders tend to be much more optimized than your own code functions. Furthermore, library calls are easier to understand and take less space in your code project. For example, if you’d need a clustering algorithm to visualize clusters of customers, you can either implement it yourself or stand on the shoulders of giants and import a clustering algorithm from an external library and pass your data into it. The latter is far more time efficient—you’ll take much less time to implement the same functionality with fewer bugs, less space, and more performant code. Libraries are one of the top reasons why master coders can be 10,000 times more productive than average coders.</p>
<p>Here’s the two-liner that imports the <a href="https://blog.finxter.com/tutorial-how-to-run-k-means-clustering-in-1-line-of-python/" target="_blank" rel="noreferrer noopener" title="[Tutorial] How to Run K-Means Clustering in 1 Line of Python?">KMeans </a>module from the scikit-learn Python library rather than reinventing the wheel:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
</pre>
<p>If you’d want to implement the KMeans algorithm, it’ll take you a few hours and 50 lines of code—and it’ll clutter your code base so that all future code will become harder to implement.</p>
<h3>Principle 6: Use the Right Names</h3>
<p>Your decisions on how to name your functions, function arguments, objects, methods, and variables uncovers whether you’re a beginner, intermediate, or expert coder. How? In any programming language, there are many naming conventions that are used by all experienced coders. If you violate them, it immediately tells the reader of your code base that you’ve not had a lot of experience with practical code projects. The more such “tells” exist in your code, the less serious will a reader of your code take it.</p>
<p>There are a lot of explicit and implicit rules governing the correct naming of your code elements. These rules may even differ from programming language to programming language. For example, you’ll use <code>camelCaseNaming</code> for variables in the Java programming language while you’ll use <code>underscore_naming</code> in Python. If you start using camel case in Python, everyone will immediately see that you’re a Python beginner. While you may not like this, it’s not really a big problem to be perceived as a beginner—everyone has been one at one point in time. Far worse is that other coders will be negatively surprised when reading their code. Instead of thinking about what the code does, they start thinking about how your code is written. You know the principle of least surprise—there’s no value in surprising other coders by choosing unconventional variable names. </p>
<p>So, let’s dive into a list of naming rule of thumbs you can consider when writing source code. This will speed up your ability to learn how to write clean code names. However, the best way to learn is to study the code of people who are better than you. Read a lot of programming tutorials, join the StackOverview community, and check out the Github code of open-source projects.</p>
<ul>
<li><strong>Choose descriptive names.</strong> Say you create a function to convert currencies from USD to EUR in Python. Call it <code>usd_to_eur(amount)</code> rather than <code>f(x)</code>.</li>
<li><strong>Choose unambiguous names.</strong> You may think that <code>dollar_to_euro(amount)</code> would be good name as well for the previously discussed function. While it is better than <code>f(x)</code>, it’s worse than <code>usd_to_eur(amount)</code> because it introduces an unnecessary degree of ambiguity. Do you mean US, Canadian, or Australian Dollar? If you’re in the US, the answer may be obvious to you. But an Australian coder may not know that the code is written in the US and may assume a different output. Minimize these confusions!</li>
<li><strong>Use Pronounceable Names.</strong> Most coders subconsciously read code by pronouncing it in their mind. If they cannot do this subconsciously because a variable name is unpronounceable, the problem of deciphering the variable name takes their precious attention. They have to actively think about possible ways to resolve the unexpected naming. For example, the variable name <code>cstmr_lst</code> may be descriptive and unambiguous, but it’s not pronounceable. Choosing the variable name <code>customer_list</code> is well worth the additional space in your code!</li>
<li><strong>Use Named Constants, Not Magic Numbers</strong>. In your code, you may use the magic number 0.9 multiple times as a factor to convert a sum in USD to a sum in EUR. However, the reader of your code—including your future self that rereads your own code—has to think about the purpose of this number. It’s not self-explanatory. A far better way of handling this “magic number” 0.9 is to store it in a variable <code>CONVERSION_RATE = 0.9</code> and use it as a factor in your conversion computations. For example, you may then calculate your income in EUR as <code>income_euro = CONVERSION_RATE * income_usd</code>. This way, their’s no magic number in your code and it becomes more readable.</li>
</ul>
<p>These are only some of the naming conventions. Again, to pick the conventions up, it’s best to Google them once (for example, “Python Naming Conventions”) and study Github code projects from experts in your field.</p>
<h3>Principle 7: Single-Responsibility Principle</h3>
<p>The single responsibility principle means that every function has one main task. A function should be small and do only one thing. It is better to have many small functions than one big function doing everything at the same time. The reason is simple: the encapsulation of functionality reduces overall complexity in your code. </p>
<p>As a rule of thumb: <strong><em>every class and every function should have only one reason to change.</em></strong> If there are multiple reasons to change, multiple programmers would like to change the same class at the same time. You’ve mixed too many responsibility in your class and now it becomes messy and cluttered.</p>
<p>Let’s consider a small examples using Python code that may run on an ebook reader to model and manage the reading experience of a user (see <strong>Listing 5-5</strong>).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Book: def __init__(self): self.title = "Python One-Liners" self.publisher = "NoStarch" self.author = "Mayer" self.current_page = 0 def get_title(self): return self.title def get_author(self): return self.author def get_publisher(self): return self.publisher def next_page(self): self.current_page += 1 return self.current_page def print_page(self): print(f"... Page Content {self.current_page} ...") python_one_liners = Book() print(python_one_liners.get_publisher())
# NoStarch python_one_liners.print_page()
# ... Page Content 0 ... python_one_liners.next_page()
python_one_liners.print_page()
# ... Page Content 1 ...
</pre>
<p><em><strong>Listing 5-5:</strong> Modeling the book class with violation of the single responsibility principle—the book class is responsible for both data modeling and data representation. It has two responsibilities.</em></p>
<p>The code in <strong>Listing 5-5</strong> defines a class <code>Book</code> with four attributes: title, author, publisher, and current page number. You define getter methods for the attributes, as well as some minimal functionality to move to the next page. The function <code>next_page()</code> may be called each time the user presses a button on the reading device. Another function <code>print_page()</code> is responsible for printing the current page to the reading device. This is only given as a stub and it’ll be more complicated in the real world. While the code looks clean and simple, it violates the single responsibility principle: the class Book is responsible for modeling the data such as the book content, but it is also responsible for printing the book to the device. You have multiple reasons to change. You may want to change the modeling of the book’s data—for example, using a database instead of a file-based input/output method. But you may also want to change the representation of the modeled data—for example, using another book formatting scheme on other type of screens. Modeling and printing are two different functions encapsulated in a single class. Let’s change this in<strong> Listing 5-6</strong>!</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Book: def __init__(self): self.title = "Python One-Liners" self.publisher = "NoStarch" self.author = "Mayer" self.current_page = 0 def get_title(self): return self.title def get_author(self): return self.author def get_publisher(self): return self.publisher def get_page(self): return self.current_page def next_page(self): self.current_page += 1 class Printer: def print_page(self, book): print(f"... Page Content {book.get_page()} ...") python_one_liners = Book()
printer = Printer() printer.print_page(python_one_liners)
# ... Page Content 0 ... python_one_liners.next_page()
printer.print_page(python_one_liners)
# ... Page Content 1 ...
</pre>
<p><em><strong>Listing 5-6:</strong> Adhering to the single responsibility principle—the book class is responsible for data modeling and the printing class is responsible for data representation.</em></p>
<p>The code in <strong>Listing 5-6</strong> accomplishes the same task but it satisfies the single responsibility principle. You create both a book and a printer class. The book class represents book meta information and the current page number. The printer class prints the book to the device. You pass the book for which you want to print the current page into the method <code>Printer.print_page()</code>. This way, data modeling and data representation are decoupled and the code becomes easier to maintain.</p>
<hr class="wp-block-separator"/>
<p>Do you want to develop the skills of a <strong>well-rounded Python professional</strong>—while getting paid in the process? Become a Python freelancer and order your book <a href="https://amzn.to/2Re2JqO" target="_blank" rel="noreferrer noopener"><strong>Leaving the Rat Race with Python</strong></a> on Amazon (<em>Kindle/Print</em>)!</p>
<div class="wp-block-image">
<figure class="aligncenter size-medium is-resized"><a href="https://amzn.to/2Re2JqO" target="_blank" rel="noopener noreferrer"><img loading="lazy" src="https://blog.finxter.com/wp-content/uploads/2020/08/final_cover-200x300.jpg" alt="Leaving the Rat Race with Python Book" class="wp-image-11850" width="200" height="300" srcset="https://blog.finxter.com/wp-content/uploads/2020/08/final_cover-200x300.jpg 200w, https://blog.finxter.com/wp-content/uplo...scaled.jpg 683w, https://blog.finxter.com/wp-content/uplo...8x1152.jpg 768w, https://blog.finxter.com/wp-content/uplo...4x1536.jpg 1024w, https://blog.finxter.com/wp-content/uplo...5x2048.jpg 1365w, https://blog.finxter.com/wp-content/uplo...50x225.jpg 150w" sizes="(max-width: 200px) 100vw, 200px" /></a></figure>
</div>
<h2>References:</h2>
<ul>
<li><a href="https://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle--net-36074" target="_blank" rel="noreferrer noopener">https://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle–net-36074 </a></li>
<li><a href="https://en.wikipedia.org/wiki/Single-responsibility_principle" target="_blank" rel="noreferrer noopener">https://en.wikipedia.org/wiki/Single-responsibility_principle</a></li>
<li><a href="https://medium.com/hackernoon/the-secret-behind-the-single-responsibility-principle-e2f3692bae25" target="_blank" rel="noreferrer noopener">https://medium.com/hackernoon/the-secret-behind-the-single-responsibility-principle-e2f3692bae25</a></li>
<li><a href="https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8263157&casa_token=Ydc5j4wwdWAAAAAA:iywl9VJ_TRe_Q3x2F7-XOgKHvrnz7TuJhBQ8iDtsSVDv1WXTGN-bCSscP0WjSs7X7LVXJFGNfgM&tag=1" target="_blank" rel="noreferrer noopener">https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8263157&casa_token=Ydc5j4wwdWAAAAAA:iywl9VJ_TRe_Q3x2F7-XOgKHvrnz7TuJhBQ8iDtsSVDv1WXTGN-bCSscP0WjSs7X7LVXJFGNfgM&tag=1</a></li>
<li><a href="https://raygun.com/blog/costly-software-errors-history/" target="_blank" rel="noreferrer noopener">https://raygun.com/blog/costly-software-errors-history/</a></li>
</ul>
<h2>Where to Go From Here?</h2>
<p>Enough theory, let’s get some practice!</p>
<p>To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?</p>
<p><strong>Practice projects is how you sharpen your saw in coding!</strong></p>
<p>Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?</p>
<p>Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.</p>
<p>Join my free webinar <a rel="noreferrer noopener" href="https://blog.finxter.com/webinar-freelancer/" target="_blank">“How to Build Your High-Income Skill Python”</a> and watch how I grew my coding business online and how you can, too—from the comfort of your own home.</p>
<p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">Join the free webinar now!</a></p>
<p>The post <a href="https://blog.finxter.com/tips-to-write-clean-code/" target="_blank" rel="noopener noreferrer">7 Tips to Write Clean Code</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>
https://www.sickgaming.net/blog/2020/11/...lean-code/