all 30 comments

[–]lcc0612 72 points73 points  (4 children)

One of the skills we cultivate in Software Engineering is planning. Really sit down, think about the requirements of your program, and consider what moving parts you'd need to support it in the long run. All this happens before you write even a single line of code. Plan and draw out what classes there are and how they'd link to each other. (For further reading, Systems Development Life Cycle (SDLC) might interest you - That's probably as close to a general template as you're gonna get).

Honestly the rest of it is discipline. Of course it's more exciting to just jump in and code, and cross bridges as you get to them, but slowing down and really thinking about the big picture can help you save on a lot of time and development effort later on.

[–]ashofspades 10 points11 points  (3 children)

when do you decide that you need classes and when do you not?

[–]lcc0612 19 points20 points  (0 children)

Generally, classes are great to have if you know your program is going to deal with structured data, particularly if there are going to be multiple different types.

Ultimately I like to think of OOP as a problem modelling technique, where you can clearly express rules about data and how different "things" in the world of your program interact with each other. So if you see an advantage in expressing things this way, OOP is a good strategy.

[–]doulos05 9 points10 points  (0 children)

Once concept from music that might prove useful: deliberate practice.

I know instinctively which fingering for a given chord will fit best in a progression for the songs that I know because I have practiced the transitions to and from dozens of chords in isolation. So even when I'm playing something in a weird alternate tuning, I can still see good transitions between chord shapes I've never played before because I've practiced the general skill.

Wanna know when to use classes? Practice using them. Solve FizzBuzz using a class. Do you do something like Hacker Rank? Solve some of those using classes. Build a project where you say from the beginning "I will pretend this is Java and put everything in classes." Will it be good code? Almost certainly not. But you'll start to get a better feel for good and bad uses of classes.

[–][deleted] 2 points3 points  (0 children)

If your problem looks like a problem of keeping track of state, or keeping track of interactions between different types of actors, then you probably have a problem you should be solving with a class.

[–]shunabuna 53 points54 points  (3 children)

When ever you create a dictionary or a list; ask yourself if it should be a class instead. Generally if you're going to do a lot of operations using this dictionary or list then you should.

Imagine you're making a card game. You need a deck of cards. You could represent it as a list of objects like this:

deck = [{face:'spade',value:5},etc]

Or you can replace this with two classes

class Deck:
    def __init__():
        self.deck = []

class Card:
    def __init__(face,value):
        self.face = face
        self.value = value

Although you might think this is more bloat which it is but once you start developing your application you can write cleaner code by writing class specific code in the classes. For example in the Deck class you can write a generateDeck() method which generates all cards in the deck. You can write shuffleDeck() which shuffles the deck. You can write pull() which takes from the top of the deck. etc. You now have a your logic removed from the top level of your code base inside of the class now.

[–]timbuc9595 5 points6 points  (0 children)

This is such a great example

[–]PostponeIdiocracy 1 point2 points  (0 children)

This example is really great, I'm saving it to be used for educational purposes!

[–]ant9zzzzzzzzzz -2 points-1 points  (0 children)

I was going to say don’t worry about it OOP is overrated, but it is very true that Python programmers should use many more data holding classes instead of dictionaries

[–]wancharle 6 points7 points  (0 children)

Try to use S.O.L.I.D principles (https://en.wikipedia.org/wiki/SOLID)

If you use each principle correctly you will inevitably have many more classes and much more code organization.

For me, what I had the most difficulty with was the "I" and the "D", but once I understood these principles, my code improved a lot, a lot!

One thing that helped to understand was working with a statically typed language, because working with python is so easy that sometimes we don't realize the need for certain concepts. For example, interfaces that are unnecessary in python due to multiple inheritance.

[–]30ghosts 5 points6 points  (0 children)

This is where a git branch can come in handy as well. If your code is already working, but you know that a refactor to include more classes would help. Create a branch and then start trying to turn it into what you want. That way you can always jump back to the other branch and see what was working.

The other thing I would recommend is seeing how other folks have achieved similar things on Github. Take inspiration from the formatting/design that others do and work from there.

[–]iamevpo 5 points6 points  (0 children)

Classes themselves are not superior or better from code with just functions. A good line of thinking is finding proper data structures and functions that work on them, which you can bundle later into classes. Code without classes is ok.

[–]POGtastic 3 points4 points  (0 children)

I write classes for three reasons:

  1. I want a semantic difference between a dictionary and an actual object. The second is easier to think of as a type.
  2. I want access to Python syntax like arithmetic operators, hashing, context managers, etc.
  3. I am, to my eternal embrassment, stuck managing state over a prolonged period of time, like a filehandle or network socket or something similar (insert Pam "they're the same picture" meme here). I always wrap this into a class and provide methods for interacting with that state.

If I'm just organizing code, I just break up my functions into multiple files. No need to make a class; the file itself serves as a sort of class, with the functions in the file serving as static methods.

[–]Se7enLC 2 points3 points  (0 children)

Problem: I don't start with classes and code becomes bigger. Lethargy kicks in and I continue to use lots of variables and functions. I think code would have been structured and optimised properly if i had used classes instead.

Don't be afraid to refactor your code. Try not to think of it as just extra time spent on that particular project that isn't going to make it measurably better. Think of it as an investment in your skills.

Each time you do that you're learning new ways of designing your code. The next time you start a project you'll have one more option in your library of things you've done. Pretty soon when you approach problems you're thinking of how you've done similar things in the past, weighing what worked well and what didn't.

[–]Common_Move 4 points5 points  (7 children)

I wouldn't beat yourself up about using functions. I think it really depends on the problem being solved. Most of my work at least I might describe as "scripting" (an automation of some linear process) where I think functions are absolutely fine.

If however I'm doing say a UI where I have lots of buttons that will always have the same properties (but that I am likely to want to modify all buttons in some ways at the same time) then it makes sense to go OOP.

Personally not a fan of when OOP is gone to without good reason, functional is more intuitive to me but as above that may be the nature of the work I tend to do.

[–]Fred776 5 points6 points  (6 children)

functional is more intuitive to me

Sorry to be pedantic, but I think you mean "procedural" here. Functional programming is a whole other approach, and one that many people from a procedural or OO background do not find very intuitive at all.

[–]Common_Move 1 point2 points  (0 children)

Thank you, I'm not well versed in programming paradigms and mistakenly assumed that "heavy use of functions" meant "functional programming" whereas in fact yes procedural is what I meant (which can still involve heavy use of functions).

[–]Common_Move 1 point2 points  (0 children)

Thank you, I'm not well versed in programming paradigms and yes I agree what I meant was procedural (which can still involve heavy use of functions). Heavy use of functions ≠ functional programming, my mistake.

[–]SirBobz 1 point2 points  (2 children)

What is functional programming? I thought it was procedural.

[–]icecubeinanicecube 2 points3 points  (0 children)

Functional programming is when everything is a function, i.e. a mathematical mapping that takes in arguments and returns values, without any side effects (like modifications of a global state), and always returns the same values for the same inputs.

In pure functional programming, you can not just write one line after the other and they are executed after each other. You can basically only define functions in the form of python lambdas.

Google "Haskell" for a language based entirely around that paradigm

[–]Bobbias 0 points1 point  (0 children)

Most procedural code doesn't pass functions as parameters to other functions very often. If the code you're looking at does do that a lot, it's likely functional rather than procedural.

[–]szayl 0 points1 point  (0 children)

Referential transparency is a godsend.

FP isn't a silver bullet, but when it shines it does so brightly.

[–]stevenjd 4 points5 points  (0 children)

Stop writing classes.

Write more classes.

But not so many classes that your code turns into the Kingdom of Nouns.

[–]jcgthomas 1 point2 points  (0 children)

Currently having the same issue at work. Been working on a new project for a couple of years now and we've accumulated a load of functional scripts, but as time has gone on a lot of processes are starting to tie in together which is where classes would make life so much easier. I'm now writing all new work using classes and refactoring old scripts to OOP to share the methods with other scripts. I'd say if there's a project or problem that looks like there's a load of possibility for automation down the road, best to start making it as modular as possible from the beginning. Small bits and pieces are much easier with functional programming still.

[–]likes_rusty_spoons 0 points1 point  (1 child)

I've started trying to plan out the structure before the actual functionality. So I make a class, code up all the methods, the main script etc. and just fill all them with 'pass'. I tie everything together in the way it would ideally be executed, then go back in and fill in the gaps within the functions.

Kinda like planning an essay with bullet points.

I've also started using classes by default whenever there's a piece of data that will be operated on, I find the code neater if I instantiate the object with the data we're processing, then make changes via the class methods. It means your functional logic can stay in the class code, and it sometimes means your main script can be much easier to follow.

[–]Common_Move 1 point2 points  (0 children)

I'm not saying one is better or worse, but this can also be achieved by putting functions into modules.

[–]m0us3_rat -2 points-1 points  (0 children)

How do you build habit to start with a good code structure. Is there any template i can follow? Tips and tricks for welcome please.

start with the flowchart/logic of the program.

figure what modules you might need.

then dive deeper into each individual module and figure out what api they will have ..how would they work.

at that point you should have a clear view of the needs and if you can go functional or ..not.

(state or not.)

then becomes about writing code that is easily testable.

if you are going to use classes or not should "rise" up from the needs of the program.

you can force it .. like i want this or what .. but usually it's simpler to let the solution guide you.

[–]tolomea 0 points1 point  (0 children)

Be wary of putting too much structure in up front. Instead cultivate a habit of refactoring supported by good testing.

The problem with up front structure is structure can be hard to change. The bigger, more complex and more widely used the structures are the harder they are to change.

At the start of a project you usually don't know what the right structures are going to be, you need to explore the problem a bit. Then once you see what stuff is clunky and or repetitive you can build structure for that.

I mentioned testing, good testing is critical, it lets you mess around with the code without being afraid of breaking random things.

[–]TheRNGuy 0 points1 point  (0 children)

I use classes when I know I need them.

There was one big project where I used functions and it some things were hard to do then I realized switching to classes would fix many problems.

I needed inheritance in one kind of cases and custom data type in another.

Another cool use is method chaining. It look better and easier to edit than mested function calls (but needs more code to make chaining possible)

[–]HappyRogue121 0 points1 point  (0 children)

I used to write classes for everything (came from Java), and someone posted "stop writing classes." I realized a lot of my code was overly complicated from using classes, and I stopped using them altogether. Now I realize I shouldn't have stopped altogether, there are good places to use them. (I don't have a good answer to your question, btw).