Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] Premature Optimization is the Root of All Evil

#1
Premature Optimization is the Root of All Evil

<div></p>
<p>This chapter draft is part of my upcoming book <em><strong>“From One to Zero”</strong></em> (NoStarch 2021). You’ll learn about the concept of premature optimization and why it hurts your programming productivity. Premature optimization is one of the main problems of poorly written code. But what is it anyway?</p>
<h2>Definition Premature Optimization</h2>
<p class="has-pale-cyan-blue-background-color has-background"><em><strong>Definition</strong>: Premature optimization is the act of spending valuable resources—such as time, effort, lines of code, or even simplicity—on unnecessary code optimizations.</em></p>
<p>There’s nothing wrong with optimized code. </p>
<p>The problem is that there’s no such thing as free lunch. If you think you optimize code snippets, what you’re really doing is to trade one variable (e.g., <a href="https://blog.finxter.com/runtime-complexity-of-python-list-methods-easy-table-lookup/" title="Runtime Complexity of Python List Methods [Easy Table Lookup]" target="_blank" rel="noreferrer noopener">complexity</a>) against another variable (e.g., <a href="https://blog.finxter.com/python-profilers-how-to-speed-up-your-python-app/" title="Python cProfile – 7 Strategies to Speed Up Your App" target="_blank" rel="noreferrer noopener">performance</a>).</p>
<p>Sometimes you can obtain<a href="https://blog.finxter.com/tips-to-write-clean-code/" title="7 Tips to Write Clean Code" target="_blank" rel="noreferrer noopener"> clean code</a> that is also more performant and easier to read—but you must spend time to get to this state! Other times, you prematurely spend <a href="https://blog.finxter.com/python-one-line-to-multiple-lines/" title="Python One Line to Multiple Lines" target="_blank" rel="noreferrer noopener">more lines</a> of code on a state-of-the-art algorithm to improve execution speed. For example, you may add 30% more lines of code to improve execution speed by 0.1%. These types of trade-offs will screw up your whole software development process when done repeatedly.</p>
<h2>Donald Knuth Quote Premature Optimization</h2>
<p>But don’t take my word for it. Here’s what one of the most famous computer scientists of all times, <a href="https://en.wikipedia.org/wiki/Donald_Knuth" target="_blank" rel="noreferrer noopener" title="https://en.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a>, says about premature optimization:</p>
<p><em>“Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97 % of the time: premature optimization is the root of all evil.”</em> — <strong>Donald Knuth</strong></p>
<p>Knuth argues that most of the time, you shouldn’t bother tweaking your code to obtain small efficiency gains. Let’s dive into five practical instances of premature optimization to see how it can get you.</p>
<h2>Six Examples of Premature Optimization</h2>
<p>There are many situations where premature optimization may occur. Watch out for those! Next, I’ll show you six instances—but I’m sure there are more.</p>
<h3>Premature Optimization of Code Functions</h3>
<div class="wp-block-image">
<figure class="aligncenter is-resized"><img loading="lazy" src="https://images.pexels.com/photos/965345/pexels-photo-965345.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="Free stock photo of close-up, code, coder" width="862" height="563"/></figure>
</div>
<p>First, you spend a lot of time optimizing a code function or code snippet that you just cannot stand leaving unoptimized. You argue that it’s a bad programming style to use the naïve method, and you should use more efficient data structures or algorithms to tackle the problem. So, you dive into learning mode, and you find better and better algorithms. Finally, you decide on one that’s considered best—but it takes you hours and hours to make them work. The optimization was premature because, as it turns out, your code snippet is executed only seldom, and it doesn’t result in meaningful performance improvements.</p>
<h3>Premature Optimization of Software Product’s Features</h3>
<div class="wp-block-image">
<figure class="aligncenter is-resized"><img loading="lazy" src="https://images.pexels.com/photos/3861949/pexels-photo-3861949.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="Engineers Testing Product" width="375" height="563"/></figure>
</div>
<p>Second, you add more features to your software product because you believe that users will need them. You optimize for expected but unproven user needs. Say you develop a smartphone app that translates text into morse code lights. Instead of developing the minimum viable product (MVP, see Chapter 3) that does just that, you add more and more features that you expect are necessary, such as a text to audio conversion and even a receiver that translates light signals to text. Later you find out that your users never use these features. Premature optimization has significantly slowed down your product development cycle and reduced your learning speed.&nbsp;</p>
<h3>Premature Optimization of Planning Phase</h3>
<div class="wp-block-image">
<figure class="aligncenter is-resized"><img loading="lazy" src="https://images.pexels.com/photos/212286/pexels-photo-212286.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="Planning Phase" width="844" height="563"/></figure>
</div>
<p>Third, you prematurely optimize your planning phase, trying to find solutions to all kinds of problems that may occur. While it’s very costly to avoid planning, many people never stop planning, which can be just as costly! Only now the costs are opportunity costs of not taking action. Making a software product a reality requires you to ship something of value to the real world—even if this thing is not perfect, yet. You need user feedback and a reality check before even knowing which problems will hit you the hardest. Planning can help you avoid many pitfalls, but if you’re the type of person without a bias towards action, all your planning will turn into nothing of value.</p>
<h3>Premature Optimization of Scalability</h3>
<div class="wp-block-image">
<figure class="aligncenter is-resized"><img loading="lazy" src="https://images.pexels.com/photos/256219/pexels-photo-256219.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="Distributed System" width="945" height="551"/></figure>
</div>
<p>Fourth, you prematurely optimize the scalability of your application. Expecting millions of visitors, you design a distributed architecture that dynamically adds virtual machines to handle peak load if necessary. Distributed systems are complex and error-prone, and it takes you months to make your system work. Even worse, I’ve seen more cases where the distribution has reduced an application’s scalability due to an increased overhead for communication and data consistency. Scalable distributed systems always come at a price—are you sure you need to pay it? What’s the point of being able to scale to millions of users if you haven’t even served your first one?</p>
<h3>Premature Optimization of Test Design</h3>
<div class="wp-block-image">
<figure class="aligncenter is-resized"><img loading="lazy" src="https://images.pexels.com/photos/1366942/pexels-photo-1366942.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="Test" width="844" height="563"/></figure>
</div>
<p>Fifth, you believe in test-driven development, and you insist on 100% test coverage. Some functions don’t lend themselves to unit tests because of their non-deterministic input (e.g., functions that process free text from users). Even though it has little value, you prematurely optimize for a perfect coverage of unit tests, and it slows down the software development cycle while introducing unnecessary complexity into the project.</p>
<h3>Premature Optimization of Object-Orientated World Building</h3>
<div class="wp-block-image">
<figure class="aligncenter"><img src="https://images.pexels.com/photos/3939173/pexels-photo-3939173.jpeg?auto=compress&amp;cs=tinysrgb&amp;h=750&amp;w=1260" alt="World Building"/></figure>
</div>
<p>Sixth, you believe in object orientation and insist on modeling the world using a complex hierarchy of classes. For example, you write a small computer game about car racing. You create a class hierarchy where the Porsche class inherits from the Car class, which inherits from the Vehicle class. In many cases, these types of stacked inheritance structures add unnecessary complexity and could be avoided. You’ve prematurely optimized your code to model a world with more details than the application needs.</p>
<h2>Code Example of Premature Optimization Gone Bad</h2>
<p>Let’s consider a small Python application that should serve as an example for a case where premature optimization went bad. Say, three colleagues Alice, Bob, and Carl regularly play poker games in the evenings. They need to keep track during a game night who owes whom. As Alice is a passionate programmer, she decides to create a small application that tracks the balances of a number of players.</p>
<p>She comes up with the code that serves the purpose well.</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="">transactions = []
balances = {} def transfer(sender, receiver, amount): transactions.append((sender, receiver, amount)) if not sender in balances: balances[sender] = 0 if not receiver in balances: balances[receiver] = 0 balances[sender] -= amount balances[receiver] += amount def get_balance(user): return balances[user] def max_transaction(): return max(transactions, key=lambda x:x[2]) transfer('Alice', 'Bob', 2000)
transfer('Bob', 'Carl', 4000)
transfer('Alice', 'Carl', 2000) print('Balance Alice: ' + str(get_balance('Alice')))
print('Balance Bob: ' + str(get_balance('Bob')))
print('Balance Carl: ' + str(get_balance('Carl'))) print('Max Transaction: ' + str(max_transaction())) transfer('Alice', 'Bob', 1000)
transfer('Carl', 'Alice', 8000) print('Balance Alice: ' + str(get_balance('Alice')))
print('Balance Bob: ' + str(get_balance('Bob')))
print('Balance Carl: ' + str(get_balance('Carl'))) print('Max Transaction: ' + str(max_transaction()))
</pre>
<p><em><strong>Listing: Simple script to track transactions and balances.</strong></em></p>
<p>The script has two global variables <code>transactions</code> and <code>balances</code>. The <a href="https://blog.finxter.com/python-lists/" title="The Ultimate Guide to Python Lists" target="_blank" rel="noreferrer noopener">list </a><code>transactions</code> tracks the transactions as they occurred during a game night. Each <code>transaction</code> is a <a href="https://blog.finxter.com/the-ultimate-guide-to-python-tuples/" title="The Ultimate Guide To Python Tuples" target="_blank" rel="noreferrer noopener">tuple </a>of sender identifier, receiver identifier, and the amount to be transferred from the sender to the receiver. The <a href="https://blog.finxter.com/python-dictionary/" title="Python Dictionary – The Ultimate Guide" target="_blank" rel="noreferrer noopener">dictionary </a><code>balances</code> tracks the mapping from user identifier to the number of credits based on the occurred transactions.</p>
<p>The function <code>transfer(sender, receiver, amount)</code> creates and stores a new transaction in the global list, creates new balances for users sender and receiver if they haven’t already been created, and updates the balances according to the transaction. The function <code>get_balance(user)</code> returns the balance of the user given as an argument. The function <code>max_transaction()</code> goes over all transactions and returns the one that has the maximum value in the third tuple element—the transaction amount.</p>
<p>The application works—it returns the following output:</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="">Balance Alice: -4000
Balance Bob: -2000
Balance Carl: 6000
Max Transaction: ('Bob', 'Carl', 4000)
Balance Alice: 3000
Balance Bob: -1000
Balance Carl: -2000
Max Transaction: ('Carl', 'Alice', 8000)
</pre>
<p>But Alice isn’t happy with the application. She realizes that calling <code>max_transaction()</code> results in some inefficiencies due to redundant calculations—the script goes over the list transactions twice to find the transaction with the maximum amount. The second time, it could theoretically reuse the result of the first call and only look at the new transactions.</p>
<p>To make the code more efficient, she adds another global variable <code>max_transaction</code> that keeps track of the maximum transaction amount ever seen.</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="">transactions = []
balances = {}
max_transaction = ('X', 'Y', -9999999) def transfer(sender, receiver, amount):
… if amount > max_transaction[2]: max_transaction = (sender, receiver, amount)
</pre>
<p>By adding more complexity to the code, it is now more performant—but at what costs? The added complexity results in no meaningful performance benefit for the small applications for which Alice is using the code. It makes it more complicated and reduces maintainability. Nobody will ever recognize the performance benefit in the evening gaming sessions. But Alice’s progress will slow down as she adds more and more global variables (e.g., tracking the minimal transaction amounts etc.). The optimization clearly was a premature optimization without need for the concrete application.</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>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/premature-optimization/" target="_blank" rel="noopener noreferrer">Premature Optimization is the Root of All Evil</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/12/...-all-evil/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016