Writing reusable code

I constantly have to change and adapt old code back and forth for different purposes, but sometimes it had two versions back to achieve the same goal.

One example of this is a function that deals with prime numbers. Sometimes what I need is a list of n primes. Sometimes what I need is nth prime. I may have stumbled upon a third need for a function along the way.

Anyway, I do this, although I need to do the same processes, but just return different values. I thought there must be a better way to do this than just changing the same code all the time. The possible alternatives I have come up with are as follows:

  • Return a tuple or list, but that seems like a mess as it will include all data types, including lists of thousands of items.

  • Use the input instructions to guide the code, although I would rather it do everything for me when I hit run.

  • Learn how to use class functions to return class properties and access them where I need them. This seems to be the cleanest solution to me, but I'm not sure since I'm still new to this.

  • Just make five versions of each reusable function.

I don't want to be a bad programmer, so which choice is the right choice? Or maybe I can do something that I didn't think about.

+3


source to share


3 answers


Modular, reusable code

Your question is really important. This is important in the everyday life of programmers. This is the question:

Is my code reusable?

If this is not the case, you will end up with code shortening by having the same lines of code in multiple places. This is the best starting point for mistakes. Imagine that you want to change the behavior in some way, for example, because you have discovered a potential problem. Then you change it in one place, but you forget the second place. Especially if your code is as large as 1000, 10,0000, or 100,000 lines of code.

It is summarized in SRP , the Unambiguous Responsibility Principle . It says that each class (also applicable to functions) should have only one definition, which "should only do one". If a function is doing multiple things, you have to break it down into smaller chunks, smaller tasks.

Anytime you come across (or write) a function with more than 10 or 20 lines of (real) code, you must be skeptical. Such functions rarely adhere to this principle.

As an example, you can define individual tasks:

  • generate prime numbers one by one (generate implies use yield

    for me)
  • collect n

    prime numbers. Uses 1.and puts them in the list
  • get n

    th prime number. Uses 1. but doesn't store every number, just waits for n

    th. Doesn't consume as much memory as 2. does.
  • Find pairs of primes: uses 1., remembers the previous number and, if the difference with the current number is two, gives this pair
  • collect all pairs of primes: uses 4. and puts them in a list
  • ...
  • ...

The list is expandable and you can use it at any level. Each function won't contain more than 10 lines of code, and you won't reinvent the wheel every time.



Put them all in a module and use it from every script for Euler's prime numbers problem.

All in all, I ran a little library for my Euler problem scenarios. You can actually get used to writing reusable code in Project Euler.

Keyword arguments

Another option that you didn't mention (as far as I understand) is using optional keyword arguments. If you find small atomic functions too complicated (although I do insist that you should get used to it), you can add a keyword argument to control the return value. For example, some functions scipy

have a parameter full_output

that takes a bool. If it is False (the default), only the most important information is returned (for example, the optimized value), if it is correct, some additional information is also returned, such as how well the optimization is performing and how many iterations it takes to merge.

You can define a parameter output_mode

, with possible values "list"

, "last"

ord any.

Recommendation

Stick to small, reusable code snippets. Getting used to it is one of the most valuable things you can get from Project Euler.

Note

If you try to implement the pattern I propose for using reusable functions, you might run into a problem right away at point 1: How do I create a generator-style function for that? For example, if you are using the sieve method. But it’s not that bad.

+4


source


My guess is, create a module that contains:



  • private main function (example: the returned list of the nth first prime numbers or even something more general)
  • several wrapper / util functions that use the main code and prepare the output in different ways. (example: n-th prime)
0


source


Try to reduce your features as much as possible and reuse them.

For example, you might have a function next_prime

that is called multiple times n_primes

and n_th_prime

.

It also makes your code more maintainable, as if you came up with a more efficient way to count prime numbers, all you do is change the code to next_prime

.

In addition, you should make your conclusion as neutral as possible. If the function returns multiple values, it must return list

either a generator, not a comma-separated string.

0


source







All Articles