49

I've been building an android game in my spare time. It's using the libgdx library so quite a bit of the heavy lifting is done for me.

While developing, I carelessly selected datatypes for some procedures. I used a hashtable because I wanted something close to an associative array. Human readable key values. In other places to achieve similar things, I use a vector. I know libgdx has vector2 and vector3 classes, but I've never used them.

When I come across weird problems and search Stack Overflow for help, I see a lot of people just reaming the questions that use a certain datatype when another one is technically "proper." Like using an ArrayList because it does not require defined bounds versus re-defining an int[] with new known boundaries. Or even something trivial like this:

for(int i = 0; i < items.length; i ++)
{
    // do something
}

I know it evaluates item.length on every iteration. However, I also know items will never be more than 15 to 20 items. So should I care if I evaluate items.length on every iteration?

I ran some tests to see how the app performs using the method I just described versus the proper, follow the tutorial and use the exact data types suggested by the community. The results: Same thing. Average 45 fps. I opened every app on the phone and galaxy tab. No difference.

So I guess my question to you is this: Is there a threshold when it no longer matters to be proper? Is it ok to say - "so long as it gets the job done, I don't care?"

12
  • 4
    It's a question of magnitudes. Try making multi-terrabyte databases served up to the real world with searches and aggregations in subsecond response times with thousands of requests a minute. Your problem isn't big enough. Though your approach is fine, if you follow that path to it's inevitable conclusion it's a painful one that takes time to reach. Nov 20, 2012 at 22:59
  • 8
    If your language had a real FOR loop, that multiple evaluation issue wouldn't be happening. Unfortunately, the C syntax requires it, because it's not really a FOR loop; it's a WHILE loop wearing a wig and big-nose glasses, and it's required to accept any arbitrary condition (or none at all) for loop termination. Nov 20, 2012 at 23:01
  • 2
    I see your edit, but if you're trying to make the case that being drunk and reckless is OK in any context except partying on a Friday night with a designated driver, you're probably barking up the wrong tree. Nov 20, 2012 at 23:06
  • 17
    How do you know it 'evaluates' item.length on every iteration? Compilers are pretty smart. And even if it repeatedly fetch item.length, so what? I would hate to see code like 'int itemsLength = items.length; for ( ; i < itemsLength; ...)' unless there was a measured performance problem. Nov 20, 2012 at 23:24
  • 6
    Your items.length thing has absolutely nothing to do with "proper programming". It's a micro-optimization, and good programmers know better than to waste time on those until they have run a profiler and know where the real performance problems are. Micro-optimizations and good programming style are often opposites, not the same thing. Nov 22, 2012 at 8:15

10 Answers 10

67

You write a program to solve a problem. That problem is accompanied by a specific set of requirements for solving it. If those requirements are met, the problem is solved and the objective is achieved.

That's it.

Now, the reason that best practices are observed is because some requirements have to do with maintainability, testability, performance guarantees and so forth. Consequently, you have those pesky folks like me who require things like proper coding style. It doesn't take that much more effort to cross your T's and dot your I's, and it is a gesture of respect to those who have to read your code later and figure out what it does.

For large systems, this kind of restraint and discipline is essential, because you have to play nice with others to get it all to work, and you have to minimize technical debt so that the project doesn't collapse under its own weight.

At the opposite end of the spectrum are those one-off utilities that you write to solve a specific problem right now, utilities that you'll never use again. In those cases, style and best practices are completely irrelevant; you hack the thing together, run it, and get on with the next thing.

So, as with so many things in software development, it depends.

8
  • 1
    I tend to agree. At work I don't ask questions, it is crossed and dotted. But consider that a lot of things I do for work are one offs that really don't need to be maintained. Passing trend kind of things. Birthday apps, stuff that come and go. All proper there, but they really don't need to be.
    – Kai Qing
    Nov 20, 2012 at 22:54
  • 22
    One can make the case that being disciplined at all times makes it easier to be disciplined when you have to be. Some people ask questions on Stack Overflow without ever pressing the shift key, using the rationale that they can adequately convey their ideas without it, and that the English language is a fluid and evolving thing anyway. I find nothing more infuriating, except maybe virus writers who think my CPU time is free. Nov 20, 2012 at 22:59
  • 2
    @KaiQing Somebody needs to hand you 5mloc legacy application that was born in pascal and ported forward ever since, upon your first attempt at adding or changing any functionality on this application you would immediately realize why best practices exist and be enlightened. Nov 20, 2012 at 23:02
  • 5
    @KaiQing, Angry Birds has to run on multiple platforms, and if the game hangs for 2 seconds x% of the audience is going to give up on it, which translates to y less dollars for the Angry Birds folks. I bet you it's been written very, very carefully. Maybe this answers your question. If the code is just for you, who cares what you do? If there is money or other peoples time at stake then you better be very, very careful. Nov 20, 2012 at 23:21
  • 2
    @KaiQing No one can tell you the threshold for that, it's variable from project to project and on each project over time. The number of variables that effect the threshold between system being maintainable and not rely on: LOC, User base, Developer base, Type of application (cryptography vs. crud vs. drivers), Feature robustness, Redundancy requirements, Software criticality (email server vs. life support device vs. clock widget), Supported platforms, Technology stack, Amount of data being transacted or analyzed, Historical audit constraints and many more things effects how bad code can be Nov 20, 2012 at 23:21
18

There's a wise old quote: "Do not follow in the footsteps of the wise men of old. Seek what they sought." There are reasons for all of the rules of 'proper' coding. Knowing why those rules exist is more important than knowing what those rules are.

There is a rule that you shouldn't put a test that could be repeatedly recalculated in a for loop like that. In the cases that the rule was invented to remedy (where performance would really be different), it makes sense. In that case, there is only one right answer. In your example, it is known that there is no performance difference and that there can't be more than a couple dozen iterations. In this case, there are two right answers, either to apply the rule anyway, since it's simple and won't hurt anything and could help form good habits, or to ignore the rule, since there is no performance difference to worry about.

I prefer the first right answer, and you appear to prefer the second. You are not wrong about that. I think you are wrong in your idea of what 'proper' programming is about. It isn't about following a randomly selected set of rules that don't help you and have no purpose. Your not fixing the for loop in the example is actually following a very good rule against premature optimization.

Real proper programming is about following good rules that make sense in an intelligent way.

4
  • I wouldn't say I prefer the second. Someone edited my post to remove the part about my making this android game almost entirely drunk (just for fun) and as a result I am surprised to see my drunken choices made no difference on performance. I replaced some weird classes with proper ones to test. I do agree though that knowing the rules exist is more important than knowing what the rules are...
    – Kai Qing
    Nov 21, 2012 at 1:55
  • Additionally, my idea of "proper" programming is a culmination of the repetetive opinions of the stackoverflow community, as well as the collection of programmers that have come and gone at the firm I work for. Some with CI degrees, some self taught. There is a common opinion to base things off of and I tend to agree with what everyone says collectively before just deciding that one way is right and one way is wrong. Thanks for participating.
    – Kai Qing
    Nov 21, 2012 at 1:58
  • 1
    If it sounded like I was telling you off for breaking the rules, then I phrased it badly. None of the things you talked about doing are things I would object to. I was trying to point out that the "spirit of the law" is more important than the "letter of the law". Nov 21, 2012 at 4:23
  • Heh, no I didn't think you were telling me off. I was just being communicative. I asked this question for a reason and I'm glad this many people responded without voting it closed.
    – Kai Qing
    Nov 21, 2012 at 18:30
10

The proper way to look at this is diminishing returns: comparing the added benefit of developing the program to the cost of the additional development.

Diminishing returns sets in when the marginal benefit is less than the marginal time/effort.

Can you make a business case for moving items.length out of the for loop? Economically, can that change even justify the time spent trying to justifying it? Since there is no difference in the user experience, you will never get anything for even the time spent measuring (other than a useful lesson to remember). The users will not like the program any more than they do, and more copies will not be sold, as a result of that change.

This is not always easy to evaluate, because business cases are filled with unknowns and risks, and are thus susceptible to fall prey to unconsidered factors that will only become obvious in hindsight. Proposed changes can be completely nontrivial, such that they do make a big difference.

Diminishing-returns type of thinking can amount to a hunt for excuses not to take some action, and avoid taking risks, which could in hindsight prove to be a string of missed opportunities.

But sometimes it is obvious when not to do something. If some piece of development seems to require an economic miracle to occur just to pay for the cost of development (break even), it's probably a bad idea.

5
  • Very well written. In my case there was never planned return. Any return may be incidental but shouldn't be dismissed since I think some of the biggest successes started as flukes. In terms of client work, where there is not so much money at stake as there may be just aggravation if the app hangs or something becomes a minor inconvenience, it is a thicker threshold. If the benchmarks look good, but the code is known to not be the most efficient, then nobody will ever come along to audit it before the times of code progress and perhaps demand a migration anyhow... hard to say on that one.
    – Kai Qing
    Nov 21, 2012 at 0:26
  • Indeed. We can't always make some kind of objective case. Not everyone values the program in the same way. Suppose that the main utility in the program is the pleasure in working on it. That might be of no benefit to anyone else and nobody will pay for the improvements (if even there are users besides the programmer), but it's enough to justify improving it in any way whatsoever.
    – Kaz
    Nov 21, 2012 at 0:42
  • Two useful words to add to your very well written answer - "Speculative Investment" - you do it because you speculate there will be a return in the future.
    – mattnz
    Nov 21, 2012 at 1:18
  • @mattnz - what you say is true in that nobody does something for no return, even if the return is a good laugh. Almost all of my personal projects are done for the humor. Almost all of them make enough to justify their requirements. None of them have enabled me to quit.
    – Kai Qing
    Nov 21, 2012 at 1:51
  • Exactly, everyone. So first we determine what we hope to get out of writing this program, or continuing to do that. That something could be "passing the time such that it is fun". But even then, we can think: is working on such and such a thing in such and such a program the best way to achieve the most fun, or do we put the time into something else.
    – Kaz
    Nov 21, 2012 at 3:16
3

When you should not care about your code being "proper"

  • If you manage to answer the business goal, and keep it over time with low overhead. (users don't view source before they pay you)
  • MVP / POC - If writing proper code means wasting time on a concept before you know how to make money from it (if you spend years and 45 million dollars writing your app and end up closing shop because it had no market, no one cares how proper was the code)
  • When having a life threatening situation (e.g. iron man prototype 1 was a dirty hack, but it got him out of the cave right?)
  • or if you simply don't know how to write proper code (if somene manages to make a living writing non proper code, in today's unemployment, I say, better write bad code than be homeless)
  • if you simply know what your'e doing or think you can get away with it pretending you do

When to write proper code

  • If it will have a significant business impact, e.g. performance will impact the revenue, or prevent sales
  • If it's so not proper that maintaining the code becomes a business issue (high maintenance costs)
  • If you are a known programmer working on a big open source project
  • Same for a big company contributing an in-house library to the world
  • If you want to show your work as a portfolio in future interviews
2
  • 1
    Sadly there is another one in the not caring to be proper list that many people are blessed to not know: When a client vomits up an old system into your care and tells you they need it done in a week. Sometimes the time and/or budget do not lend themselves to proper coding and your attention on the project is more of a grace than a business transaction. For example, if their code uses largely deprecated methods but needs some patching (speaking in a web scenario). Can't fix the whole thing. Must get dirty.
    – Kai Qing
    Nov 21, 2012 at 18:33
  • "If it's so not proper that maintaining the code becomes a business issue (high maintenance costs)." This threshold is actually considerably lower than most inexperienced developers are inclined to believe. Writing solid code often pays itself back within hours, not days or months. Nov 26, 2012 at 17:39
2

Is performance your main concern? Is that what you're trying to maximize?

If so, there is a fundamental lesson to learn, and if you do, you'll be one of the few.

Don't try to "think" what you should do to make it faster - that's guessing. If you're asking "Should I use this container class or that one?", or "Should I put length in the loop condition?", you're like a doctor who sees a patient and tries to decide what treatment to give without actually questioning or examining the patient.

That's guessing. Everybody does it, but it doesn't work.

Instead, let the program itself tell you what its problem is. Here's a detailed example.

Do you see the difference?

3
  • I would say my only concern was that in my tests I noticed no performance differences between the improper and proper use of datatypes for the specified scenario. As in your suggestion, I overloaded the class with more data to see if it was just too little to make a difference. In the end, both performed equally. Granted, I'm just making a basic RPG type game. It's not like banking software or something complex. But it has made me wonder if it would be better for business to not be so proper all the time.
    – Kai Qing
    Nov 23, 2012 at 18:57
  • Since performance is your concern, you should be asking the program what you should be looking at, not asking if your preconceived question makes a difference. Please click on this link, and do what it says. It will tell you what the program is really spending time at, and that will tell you how to make it faster. Nov 23, 2012 at 20:08
  • Well, performance was my basis for questioning procedure, not necessarily a concern. I'm not looking to benchmark per say. Merely observing that inefficient code made no performance difference. It is essentially transparent to the user how efficient or inefficient the program was, therefore making the concern for such profiling irrelevant. Granted, I had to have some concern to benchmark in the first place, but it was mostly curiosity. And if the product is finished and it is noticeably slow then yes, a profiler makes sense. Thanks for the link
    – Kai Qing
    Nov 23, 2012 at 21:19
2

Your question is "so long as it gets the job done, I don't care?"

My answer is, "you never know what will happen to your code." I've been involved in so many projects that started out as "hey let me write this quick thing to take care of a user's problem." Write it, put it out there, never think about it again.

One time, that thing I wrote morphed into "oh, now the user's entire department wants to use that code," which before I could turn around became "the entire company is using that code and now I have to prove it will survive an audit and there's a 20-person code review scheduled for tomorrow and some vice president has already sold it to our customers."

I realize you're "just writing an android game in your spare time" but you never know if that game will take off and become your ticket to fame and fortune. Worse yet, that game could become your ticket to infamy because it keeps crashing people's phones. Do you want to be the person who gets a job offer because someone's kids can't stop playing your game on their phones, or do you want to be the person who gets vilified on message boards like this one?

1

The answer is that it never matters, and it always matters....

It never matters because programming, proper or not, is a way of achieving a goal, not a goal in itself. If that goal is achieved without "proper" programming that's fine (from a business perspective it's often best if the goal can be achieved with no programming).

It always matters because proper programming is a tool that will aid you in achieving your goals. The proper way of doing things is simply a recognition that doing it another way causes more pain in the long run than it saves.

Which answers the question of when you can ignore it -- when you're sure that another way will be easier in the long run (possibly because there will be no long run).

One off tools are typically done as quick and dirty as you can, with little to no error checking or other validation, no logging of exceptions, cut-n-paste code with minor changes or even no changes instead of generic functions, and so forth.

Just watch out: sometimes those quick and dirty apps take on alife of their own, which means all of the short cuts bite you in the...

4
  • 1
    "never" and "always" cancel each other. Making your answer both good and bad. Nov 22, 2012 at 16:06
  • @user1598390: their canceling each other out was the point. Cancel the dogma, and you're left with as it seems useful. And you'll get it wrong and learn from that.
    – jmoreno
    Nov 23, 2012 at 7:14
  • I want to say I agree with you but I wouldn't have taken it to such extremes. I don't think one offs are often just spit out, escaping testing or debugging. Just cause it isn't optimized and perfectly designed doesn't make it any less of a product if the performance and stability are not affected by the shortcust. Which is ultimately my point and why I wonder why everyone makes such a stink over coding examples that aren't top of the line. It happens a lot on stackoverflow.
    – Kai Qing
    Nov 23, 2012 at 18:42
  • @KaiQing: Testing and debugging happen of course, but are generally limited to what exists at the moment -- so for instance if the process might fail with a file that had a UTF encoding, and none of the files you're actually working on do, you don't test that. Optimization should be done when a performance problem has been identified. As for why a stink over non-top of the line coding examples on SO -- I think that's a function of the site goals. It aims to be permanent resource, code in answers (and even questions) are thus looked at as if they will be a template that others use.
    – jmoreno
    Nov 24, 2012 at 2:40
1

Or even something trivial like this:

for(int i = 0; i < items.length;i ++) {
     // do something 
}

I know it evaluates item.length on every iteration. However, I also know items will never be more than 15 to 20 items. So should I care if I evaluate items.length on every iteration?

Actually in the final code, items.length will not be evaluated in every iteration because the compiler optimizes it. And even if it weren't, length is a public field in the array object; accessing it doesn't cost.

So I guess my question to you is this: Is there a threshold when it no longer >matters to be proper? Is it ok to say - "so long as it gets the job done, I >don't care?"

It really depends on what you expect from your end product; the difference between an average product and a great product relies in details. A car like Tata Nano and a car like Mercedes S "gets the job done" - it takes you from one place to another. The difference relies in details: engine power, comfort, safety and others. It is the same with any product that exists, including software products; for example why would anyone pay to Oracle, IBM or Microsoft for Oracle database, DB2 or MS SQL Server since MySQL and Postgre are free?

If you want to pay attention to the details and obtain a high quality product you should care about this stuff (and about other stuff, obviously).

3
  • I don't think I agree with that though. In my post I mention no difference in performance. That would suggest there is no average or great product, but an equal balance despite the shortcomings of one. I would agree with your statement, however, if there was a specific project of great importance we were all using as the comparison. But abstractly, the general observation is that in this anonymous project, a decidedly inefficient class performed equally with an optimized one. So then, is it ok to adopt a slack attitude on this or argue for perfection every time?
    – Kai Qing
    Nov 23, 2012 at 19:01
  • @Kai Qing A single class doesn't (or shouldn't) make much of a difference. I said it: if you expect your product to be a high-quality product then pay atention to details (even if it means a possible little optimization or a carefull design); on the other hand if the only thing that you want is a functional system then probably you shouldn't pay much atention to tiny details.
    – Random42
    Nov 23, 2012 at 20:17
  • Yes, you're right it shouldn't make a difference even if only a little care is placed in its design. But it can make a difference depending on its purpose or if in general its purpose transformed over time and became something it was not intended to be. Seen that before, but I'm just going on a tangent here. To be fair, a product can be high quality without having to be any more than functional.
    – Kai Qing
    Nov 23, 2012 at 21:32
1

If you are programming at home for yourself then maybe you can cut a few corners; and when you are experimenting and trying things out this is completely justified.

However take care. In the example you give there's not really any need to cut that corner, and you need to be careful. This could start a trend and bad habits that you do at home could creep into your code at work. Far better to practice and improve on good habits at home and let them seep into your code at work. It'll help you and it'll help others.

Any programming you do and any thinking you do about programming is exercise. Make it worthwhile, otherwise it'll come back and bite you.

Look on the good side though. You've asked about this so maybe you're already aware of the point I'm making.

2
  • 1
    Yeah, I am aware but the point of the question is mostly that in the smaller, contained context there doesn't appear to be a reason to be so proper. In all my years of programming, there really hasn't been a whole lot of creeping back to bite us. I doubt that we're so proper. I think it's that languages and expectations change like normal software. Some less than others. But in the end the inefficiency of one project may only be realized when the project is in the past and no longer essential. It makes it hard to justify the headache of being so rigid.
    – Kai Qing
    Nov 28, 2012 at 19:17
  • That's a fair point. Today's rules can be tomorrow's restrictions. I don't enjoy being told what to do, but I do have respect for others who have gone before and have learned the hard way. Sometimes though it can be interesting to find out what rules are useful and what are now past their sell-by date. Nov 28, 2012 at 22:00
1

If a furniture maker was making a piece of furniture to be used where the quality wasn't of utmost importance or where the quality might go unnoticed, should they still try to make their cuts straight, and do a proper job joining the pieces together?

Many people see software as craftsmanship. What we build shouldn't only perform a function, it needs to be reliable, maintainable, robust. Making such software requires skill, and that skill comes from practice.

So, even though the choice of a looping construct for what you are working on today may not matter, the fact that you strive to use the proper constructs at all times will, over time, make you a better programmer.

3
  • I've encountered instances in programming where the code did not need to be maintainable or perform outside the needs. Like kiosk utilities for trade shows or events that are very specific and not likely to be reused. In the case of my own game - I am the only one maintaining it, so that argument may not be the most applicable. I still have doubts about the common perspective on "better programmer" because rigid adherence to guidelines, maintainability and proper usage of datatypes can be enough of a discouragement to not complete the project. If the code works as expected, why perfect it?
    – Kai Qing
    Aug 6, 2013 at 23:54
  • Even if the software you're building right_now doesn't need to be maintained, writing the software as if it did strengthens your coding skills. When you finally do have to write maintainable code, you'll be able to do it more easily. Aug 7, 2013 at 1:38
  • I have to write maintainable code all the time. Just in some cases it doesn't have to be. However, I do have plenty of experience so I typically know when and where to cut corners. The point of this post was to just stir up conversation about the threshold of proper and sloppy for whatever purpose. My example only lightly brushes on it since the example given is mostly harmless in a smaller application. However, if I were writing bank software I would never be so careless.
    – Kai Qing
    Aug 7, 2013 at 1:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.