2

I keep hearing about writing good code and writing bad code when you first start. Afterall, if it runs and gets the job done with 0 issues is that not enough? Can you use this as an example? I worked with what I knew and what I had to learn so I am sure it can be picked apart. Besides the PEP8 and stuff what is GOOD code?

import random
    def cownbull():
"""This one generates a non repeating random number"""
        def cownbull2():
    """This one is running the game due to local variable problems; keyboard 
                                                          almost thrown"""
            print(num2guess, 'is the generated number')
            print("Let's play a game of Cowbull!")  # explanation
            print("I will generate a number, and you have to guess the 
            numbers one digit at a time.")
            print("For every number in the wrong place, you get a cow. For 
            every one in the right place, you get a bull.")
            print("The game ends when you get 4 bulls!")
            print("There are no repeated digits")
            guesses = 0
            cow = 0
            bull = 0
            while True:
                print("cows:", cow,'|','bulls:',bull,'|','guesses:',guesses)
                cow = 0
                bull = 0
                user = input('Guess a four digit number: ')
                if len(user) >4:
                    print('type four digits!')
                    cownbull()
                guesses = guesses + 1

                for x in user:
                    for y in str(num2guess):
                        if x == y:
                            if user.index(x, 0, 4) ==
                                            str(num2guess).index(y, 0, 4):
                            bull += 1
                                if bull == 4:
                                    print('Nice game!')
                                    cownbull()
                            else:
                                cow += 1
                        else:
                            pass
        num2guess = random.randint(1000, 9999)
        count = 0
        while count < 4:
            for i in str(num2guess):
                count = count + 1
                print(i)
                str2guess = str(num2guess)
                print(str2guess.count(i))
            if str2guess.count(i) != 1:
                print('calculating new number....')
                cownbull()
            else:
                cownbull2()


cownbull()
John Ketterer
  • 137
  • 1
  • 1
  • 9
  • 1
    [codereview.se] is a better place to ask for stylistic questions like this. – Barmar Dec 15 '18 at 02:54
  • 3
    There's more to programming than just "the code works". Does it meet expectations? Does it pass all testing? Is it reliable, adaptable, readable, extendable, complex? Your code for example would feature a lot of "code smells", which would require refactoring to take place (hence PEP8) – TerryA Dec 15 '18 at 02:57
  • 1
    "The code works" is the minimum requirement for calling yourself a programmer. Beyond that, code needs to be clear, concise, maintainable, and above all demonstrate good taste. Programming is, after all, a craft. –  Dec 15 '18 at 03:24
  • Thank you, especially Pythonista. I think information like this is rarely found in the tutorials I have been using online. There are many to pick from and it is hard to pick one when you aren't sure what has good material. You have pointed me in a good direction to learn more! Thank you so much – John Ketterer Dec 15 '18 at 04:58

1 Answers1

3

2020 Update: I thought I should update this in reference to my COBOL comments below and COVID-19 and why good code is important. Because, it affects peoples lives as we're clearly seeing now from non-functional state and governmental systems.

Afterall, if it runs and gets the job done with 0 issues is that not enough?

No. Not even close. This is what annoys me and nearly every other software developer. Let's take a scenario that happens far too often.

You made a program and it "just works". But, your code is shit. Then other people have to work on it. Guess what? I get to dig through a bunch of copy pasted garbage, unpythonic code, rework all of it, assuming I can even unpiece the Frankenstein logic someone managed to throw together with 0 comments and logical train of thought. This isn't directed at your code - but the degree to which it happens out in the "wild".

It's unmanageable, especially when it needs to be added to, if you opened your editor 6 months from now with what you just coded would you even have a clue what it does? And then people that code this way expect other developers to be able to work with their "functional" code. Not good enough.


There are code bases people don't touch for years - that then become legacy code bases - which are monstrosities (looking at you COBOL) that only a handful of people know anything about and are next to impossible for the next dev or team to manage to a reasonable degree.

This is a very simple case.. You have maybe 100 lines here. What happens when it's hundreds of thousands and reads this way? What happens when you have an entire team of developers each of which are pushing code, different branches, merges, etc. Software development is complicated and practices exist to minimize error, fluency between developers, and limit complexity / bad code.


Clean code is an art form few people have mastered.

Zen of Python

Clean Code - you can find this elsewhere or at your library (or equivalent dependent upon locale) likely if cost is an issue. I highly recommend reading some form of a book on clean coding. It will be eye opening.

Besides the PEP8 and stuff what is GOOD code?

In one sentence, I should be able to open my editor look at your code read it as a bunch of simple logic - nearly identical to English sentences thanks to Python - top down without pausing and go "yeah that's what I expected"

You'll have people argue for certain design patterns such as test driven development or behavior driven and there's a lot of merit and use cases for these. However, this is focusing purely on the semantics of how your code reads. The craft of writing the code itself.


Things in your own code I'd refactor immediately and consider "code smell"

  1. Comments: """This one is running the game due to local variable problems; keyboard almost thrown""".

While comments like this are cute they aren't helpful. You want short concise comments only where needed for questionable pieces for someone entering the code base and for yourself.

  1. Nested functions like this: There are times to use closures. This is not one of them.

  2. Redundant definitions and logic: Use it where you need it, when you need it, only when you need it.

  3. General reorganization and compacting of code. Your new so you don't really now these yet, but they'll come with time. So I'm not going to nitpick this too much.

  4. Docstrings: In real code bases doc strings are used for documenting the function as the name implies. Parameters, return values, expectations, etc. Libraries even exist to generate full documentation pages from these such as sphinx

  5. Backwards compatability: This is for large codebases which need to have legacy support. If you go to almost any public repository you'll find a compat.py that bridges imports between versions.


Object Oriented Languages:

In general, we can say a few things about clean code in object oriented languages.

As the name implies an object oriented languages is centered around the definition of "objects". In python these would be your classes.

in python 2 (also works in Python 3 just "old style"):

class ClassName(object):
    ....

in python 3:

class ClassName:
    ....

Polymorphism and Inheritance

Here your class serves to encapsulate an object and it's methods / attributes. Moreover, object oriented languages inherently provide polymorphism.

Polymorphism allows you to provide an interface that acts in many forms. The name itself implies this from the Greek root "poly" meaning many and "morphism" meaning form.

Let's say I built a class to describe animals and their properties. I could built a new class for every.single.type.of.animal. Or, provide the common methods and attributes and override them when necessary. Here's a practical example of the animal kingdom

Polymorphism is a wonderful way to write clean code when appropriate. Similarly, for inheritance.


Building Blocks

One of the powerful things about object oriented languages is being able to break things into "building blocks" so to speak and mix them together to provide mixed functionality.

However, what happens when you write a ton of these tie them all together for some higher functioning object and then need to make changes or want to use it elsewhere?

Do you have to go through or take the entire object-oriented zoo with you? That's not very clean in my opinion and frustrating for developers. Use this methodology of programming cautiously.

Personally, I love it because I'm very fond of the Django web framework and love using mixins and the flexibility of some tricks here and there. So, I lean to this type of programming personally.


Summation on writing clean code in Python:

Do the above, get good at polymorphism and inheritance, follow the Zen, know how to break things apart and keep things concise without killing readability, and document your code properly. This is 90% of clean code. The rest is honing the craft.

Pythonista
  • 11,377
  • 2
  • 31
  • 50
  • 1
    "bull == 4:. Ints from -5 to 256 are cached. Using is instead of == is faster" holy hell no. This is an *implementation detail* and you should never write code that relies on it. You should only use `is` this way for things *the language, not the implementation* guarantee will be singletons, like `None`, `True`, and enums – juanpa.arrivillaga Dec 15 '18 at 07:38
  • Ah yeah fair enough. Glossed over that. Thanks for pointing it out - has been updated. – Pythonista Dec 15 '18 at 19:30
  • 1
    @Pythonista, after some experience and reading through the book you recommended I can say that was huge in developing an understanding and proficiency for the broader picture. Thank you again! – John Ketterer Apr 02 '20 at 07:26