My Java code is sloppy and I need tips on makeing it neater. Where do I start?

Disclaimer: I am new to the level1forums (and forums in general) ; however I have been following level1techs on YouTube for a year now, so please bare with me.

A Bit of Context

My Java professor is of the opinion that as long as a piece of code works I shouldn't worry about what it looks like. So when I go to ask him questions about how to make my java program more readable he brushes me off with, "As long as it works it doesn't matter." To top it off our class only meets once a week and the professor works full time at another university. He assigns projects due the next class with no time in between to ask specific questions.

Aside from my qualms with the professors teaching method, I am having a problem understanding how to apply simple java mechanics to larger problems. This leads to me piecing together code I find on the internet with little understanding of how my code works.

The Problem

We have currently been assigned to program Conway's Game of Life without using graphics. My program currently evaluates the first 3 rules of GOL; however I feel like the implementation could be much better and the code could look much neater.

The Question

So my question is...

How can I make this code more readable and what resources can I use to make my code better in the future?

code file 1: https://hastebin.com/nonocewume.java
code file 2: https://hastebin.com/upilacosik.java

ps: Iā€™m not looking for a better implementation, Iā€™m looking for how to improve my code. Feel free to give me any tips on how to ask questions better :slight_smile:

It probably wonā€™t mean much, but I am going to go ahead and qualify myself somewhat.
I am a Java dev, with nearly 2 years real world experience now. The system that I have been working on since day one is incredibly large, and has a lot of code, both old a new. The majority of what I have been doing since I started working is finding and fixing bugs in the code (whereas most people in the company tend to basically specialize in one area of the code). So I have spent a lot of time looking at a lot of code that I am not familiar with. And as such, I can tell you, at least when you are working on larger systems, and expect other people to one day have to read your code (which you should always expect), the way the code looks definitely matters. The people in my company almost never comment code (which you should always do), so the fastest thing for me is generally just reading it. Similar to how you would read a book, I skim through it. Thousands of lines a day, every day. So yes, having readable code is important to me. Readability is more important to me than making it elegant, or concise. I need it to be able to be understood. Because in a company with hundreds of java devs, like the one I work for, someone will one day have to debug my code. Pure and simple. Other people need to be able to understand it.

So with that rant out of the way, towards the end that you are getting at. I think that you are a bit too concerned with how the code looks. Again, readability is incredibly important, but that is the sort of thing that comes more after you become more accustomed to looking at code yourself. I know what code is easy to read because Iā€™ve read a lot of code. And, most place that you work will have standards on how they want the code to look. A lot of it is preference. So if the company wants you to do it a certain way, then that is how you will do it. So you need to get to where you are flexible enough to be able to read and write code however they want it. Developing your own personally style is fine though, as it makes writing code easier to do.

I think that what you should focus on more than readability right now is understanding. You really need to understand what the code is doing in order to progress your coding abilities. Knowing what it is doing and how it is doing it is the most important thing for you right now, as a beginner.

In my opinion, the best way for you to get better at writing effective and readable code is to simply read and write more code. I know that sounds like terrible advice, but after you start getting actual experience, you realize just how valuable experience actually is. I learned more in my first week of working then I did in my first few years of Computer Science schooling. And that is just the truth of it.

Now, I can go through the code, explaining what it does, and telling you how I would write it to make it more readable. But I think that developing a style that you like, and staying consistent with it once you do get it is a better choice.
For example, I really donā€™t like having the then statement in the same line as the if statement. So I would write this:
if (position[x][y + 1] == 1) { numberofneighbors += 1; }
like this:
if (position[x][y + 1] == 1) {
numberofneighbors ++;
}

Because I think that is more readable.

As for becoming better at applying java mechanics, the best thing that I think that you can do, is again experience. During your projects, it is fine to look up code examples, so long as you make sure that you understand the examples. And if you donā€™t understand them, donā€™t just use them like a black box and move on. Try to understand them. Break it down, google it, ask someone, do some reading in the java documentation.

As you start to understand more of the mechanics available to you in java, you will start to be able to effectively utilize them. You canā€™t use a hammer effectively if you didnā€™t know you had one and didnā€™t know what a hammer was. So find out the best way to solve specific problems, and any time that you encounter a new mechanism, go out of your way to understand what it does and how you can utilize it effectively.

Sorry for the wordy post, I just wish someone had told me all this stuff years ago.

EDIT: I just thought of a an analogy which I think is really applicable.
In an article I read about why professional bowlers donā€™t always get perfect scores, the author basically said, ā€œYou might think to yourself that you could do better than those professional bowlers, since you have bowled some good games in your life. But that simply isnā€™t the case. They are better than you are. Much better than you are. They are better at bowling then you are to the same extent that Lance Armstrong is better at biking than you are.ā€
And I think that sort of mentality applies here. You really donā€™t know how much better experience coders are until you start really getting a hang for it. The guys at my company that have been there for 10+ years? They are basically genies. Sure they make mistakes, and what have you, but their understanding of the system and java as well as their ability to grasp the stuff that is going on is leagues above what you or I can do that it isnā€™t even funny.

I hope that one day, I will get to a level close to that, but for now, I will keep trudging through, just like they did. And I hope that you will too.

4 Likes

This is a really helpful reply to someone who is building their skills in Java. Thanks for taking the time to post this. I will apply some of what you said to my programming. However I do quite like one line if statements. Thanks so much.

Dont take the things im about to say as rules you have to obay. You really dont, but maybe some things you end up liking. I feel like im supposed to write a wall of text about my qualifications now too, but they really are not as impressive. I just finished school and now im working my first few months not even as a programmer, but im still doing some private projects and might look to work as a programmer in the future.

Blockquote
if (position[x][y + 1] == 1) { numberofneighbors += 1; }
if (position[x + 1][y] == 1) { numberofneighbors += 1; }
if (position[x + 1][y + 1] == 1) { numberofneighbors += 1; }
if (position[x - 1][y] == 1) { numberofneighbors += 1; }
if (position[x][y - 1] == 1) { numberofneighbors += 1; }
if (position[x + 1][y - 1] == 1) { numberofneighbors += 1; }
if (position[x - 1][y + 1] == 1) { numberofneighbors += 1; }

The field is 1 or 0 anyways, right? You dont have to check anything, just add them up. And comment them, because i for instance usually use r and c for rows and columns instead of x and y and the other way around too since y would be rows (yours is more mathematically correct id say). So do something like.

numberofneighbors = position[x + 1][y] //right side
+ position[ā€¦] //top side

Or better yet use booleans imo seems more fitting. Then you canā€™t add them upp like this anymore though.

Also the naming is odd ā€œint[][] positionā€ would does not tell you what it is. Your possitions are your x and y coardinates, not the field itself, that should be more like ā€œisOcupiedā€ or something along that way. Witch is why id say use boolean instead as well. Its a smaller type too, but aside from that it also just makes more sence to use there in my oppinion.

In your other file you did use i and j for your x and y fields, witch i think you should stick to x and y. Stay away from those generic variable names if youā€™re coding more of an algorithm and/or have a fitting name for it.

For here ā€œif ((x < 0) || (y < 0) || (x > 5) || (y > 5)) { throw new Exception(ā€"); }" You also have IndexOutOfRangeException in place of Exception, witch is just something more specific. And it might even be a good idea to also check for x and y specifically and throw an exception that tells them ā€œx is out of rangeā€-specifically. Also you can use [dimension]length. So board[0].length would give you your x max length. So you can later change the board size with minimal change needed.

The Cell class also seems very odd and does not seem to accomplish anything other than introducing a new type. You can make Cell and Board classes if you really want to, but it does not seem required. Making a cell so it (actually) knows its neighbors is kinda not practical (like a list with 8 different next referencesā€¦) and thus id do the checking part in the Board / or main class. A board class makes some amount of sence, so you can make multiple boards of different sizes at the same time (and implement runnable so you can start them with or without a seperate thread), but i donā€™t see the point of a Cell class when it basically just is a single int or boolean. Unless of course you go the other route and save a cells neighborcount in the cell class and then update the neighbor count of a cells surroundings on a change of state, or something like that.

By looking at your code Iā€™d say that you are missing a check for one neighbor, if you use the simple 3x3 neighborhood there should be 8 neighbors and you have only 7, so you are missing [x-1][y-1], at least on the version that you posted hereā€¦ Generally you could define whatever the neighborhood you want, but Iā€™m guessing that you missed thisā€¦ :slight_smile:

In order to make your code more readable to yourself and others you should first understand what you are implementing, so start simple and build on that, this is good example for that, you can always add/change the rulesā€¦

When you have a good understanding of the algorithm or whatever you are coding try to write your code like a story, be descriptive with names of your variables, classes, methods, etc.
Split the problem into more smaller problems, then try to code methods that are short and to the pointā€¦ Write effective comments when necessary, try to find more about thatā€¦ There is a lot more so be sure to look around some more, check multiple sources, readā€¦ Read about what best practices areā€¦ You will always need to do some kind of researchā€¦ :slight_smile:

Some comments on your code to help you understand these principles betterā€¦ Sometimes you will just need to refactor your code or find a better way of implementing it in order improve itā€¦
https://pastebin.com/eQWkP3cm

Hope this helps and just continue to do research and to code, it will get betterā€¦ :slight_smile:

Wow, I remember when a friend sent me a c code snipped of some method called RemovePirateRoars. Witch removes /r characters from a string, because ā€œthey sound like pirate roarsā€. If youĀ“re into it and donĀ“t waste all your time with itā€¦ sureā€¦ but then more than ever before make some documentation WHY THE F*CK it is what it is!

Also as far as algorithms go of any kind, itĀ“s not illegal to use a piece of paper for the thinking process either. Sometimes helps. Especially if your problem is new-land to (you).

And some other things the Exception actually kills your program (didnĀ“t think of that at first since i was so focused on code-style and just assumed it would work), cause you cannot count neighbors on the edge of the field then. Just thought of that. xD

And i made my own very much plain gameoflife (does not even output anything, but the points are marked where one could update a window or whatever the case). So there is that. https://hastebin.com/yegejaruru.java
I mean almost i messed up the last ā€œalternativeā€ comment, but whatever.

Edit: consolidated all my posts

@1920.1080p.1280.720p

Yes, this is basically the type of advice I was looking for. Thank you for the long detailed post (I am much more partial to reading long a lengthy posts, so long as they are written well. Yours is very much like that :slight_smile: )

I understand that most people prefer the convention of seperate lines forif statements; however in this case I made the concious decision to include the then statement on the same line simply because it was so short. I like your use of numberofneighbors ++; in place of numberofneighbors += 1; and is the kind of suggestion I was looking for. Itā€™s something that makes the code easier to read and comprehend.

I understand what you mean and I believe that is exactly what I need. I think my main problem is that I have a issue with the level of complexity of what my professor is assigning vs what I can actually do. I think I should try to include a few more personal Java programming projects in my schedule to give me more experience.

From my experience in the construction industry this is abundantly clear. Everyone may be able to swing a hammer but it takes years to master using a hammer.

Thank you for your response.

@maximal

I think this would condense that section of my code quite a bit. Thank you for the tip.

The reason I used 1ā€™s and 0ā€™s is because I have future plans to incorporate the 4th rule of GOL, which statesā€¦

  1. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

I plan to flip dead 1ā€™s into 2ā€™s before rendering the board to calculate the number of dead cells in the board. Which gives my program another layer of complexity.

So Java complains when I specify IndexOutOfRangeException. If I specify Exception I can get Java to stay quiet when it runs into out of bounds exceptions. I specifically want java to skip these exceptions since numberofneighborsis simply a check. Iā€™m guessing this is very bad practice (since sometimes you could miss a error that you actually need to see). What is the alternative?

I did not realize you could specify the dimension of the length method. Hence why I thought length only pertained to single dimension arrays. This is a great suggestion.

I do not really want to create a new class but the way I have been taught Iā€™m not really sure how to run a routine any other way. The entire point of the Cell class is to make use of the numberofneighbors method. This is probably where I am struggling the most since I canā€™t really get any one on one time with my professor to explain how to implement checks without using a class. As I type this I realize that the word I am looking for is function. I will look into how to use functions better.

Thank you so much

@dok

Ahh thank you. I was trying to figure out how to get around a out of bounds exception, so I deleted that line and forgot to add it back in. I should remember to comment out lines instead of deleting them. Nice catch.

After looking at your comments on pastebin. I think the suggestions you made is really what I was looking for. I am not entirely sure when to use a class, method or function and this is my biggest weakness. I will take your advice to heart and continue to improve :slight_smile:

Actually, never mind. Iā€™ll better go sleepā€¦ lul

This is not supposed to take you a lot of time, this is not supposed to be a replacement for comments and documentationā€¦
This is not something that you should follow blindly, it has itā€™s flaws, and some times you will be better offā€¦ So balanceā€¦ If itā€™s done correctly and not overdone, it will improve your codeā€¦ When you are able to write your code like that, you probably understand it very well and that is good for beginners, less ā€˜spaghetti codeā€™ā€¦ It will take a bit of your time, sure, but so will any other technique, that is the process of learningā€¦

Well think about it, what is a class, what does it provide? How could you take advantage of that?
In java function and method are basically the same, term method is used in javaā€¦ In some other languages these terms are related to slightly different things, you could look that up for c/c++ for exampleā€¦ Generally you refer to a name callable piece of code which performs some operations with or without parameters and optionally returns a valueā€¦

The things Iā€™ve pointed out in comments of your code are important for you to understand in order to make a better structure and more optimized code, and to avoid unnecessary calls and objects etcā€¦ All of that will result with easier to read codeā€¦ One more important principle is KISS (Keep it simple, stupid), that one is self explanatory :slight_smile:

I think one of my very first learning books for Java in one of itā€™s very first chapters explained the word syntax.
Basically everyone has their own style.
Develop your own style, and just things your way.
ifā€¦
import java.util.Arrays;
import java.util.Random;
public class GOL { public static void main(String[] args) {Cell newcell = new Cell(0);int board[][] = new int[5][5]; Random rand = new Random(); //https://stackoverflow.com/questions/43314281/random-matrix-fill-between-1-and-0-in-java
for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++){board[i][j] = rand.nextInt(2);try{if (newcell.getNumberofNeighbors(i, j, board) < 2){board[i][j] = 0;}
if (newcell.getNumberofNeighbors(i, j, board) > 3){board[i][j] = 0;}}catch (Exception e) {//https://stackoverflow.com/questions/409784/whats-the-simplest-way-to-print-a-java-array
System.out.println(Arrays.deepToString(board).replace("], " + ā€œ[ā€, ā€œ\nā€));}}}}}

is your style, go for it.
Basically only write what you, yourself understand, dont cater your syntax to what you expect other people to understand.
The compiler understands regardless.
In my eyes your syntax is very understandable.
I sometimes get grievances because i like the
if( x != y)
{
do this.
}
structure, but for some reason random_dev_01 prefers
if( x!=y ) {
do this.
}
and i mean does it REALLY matter that much that you have to relearn your muscle memory from writing
()
{
to writing
() {
your code is fine. Once you pass it to a compiler it doesnā€™t matter, he is your friend, and he understands you fine,
and if not heā€™ll surely tell you in usually red text.
And the dev who complains that he doesnā€™t understand.
()
{

}
is lying or retarded, and should be on welfare, not working as a dev.
also as time passes and your experience grows, your syntax will change alot.

I use a package called atom-beautify in combination with another program called uncrustify which does most of my formating for me. Thatā€™s why some of my conventions may not seem typical. I really like the package since I dont have to go chasing {} anymore.

Can atom actually substitute for a ā€œrealā€ Java-IDE, like IntelliJ, Netbeans, Eclipse? I currently use IntelliJ Community Edition, because iā€™ve been using IntelliJ Ultimate in school, but now i no longer get a free licenseā€¦ More annoying than i thought it would be. Things like databases, you have to do the whole configuration part manually. And another thing im not really sure about is css files. I think ultimate did help you with css style-sheets in JavaFX or JSF, but i honestly cannot recall 100%.
Probably would suggest you try netbeans unless you get intellij ultimate for free, but i did not use that one for a long time either.

If you have multiple states like that, you can use an enum to make it more readable. Then you have 3 states, like Empty, Alive, Dead and maybe a forth in Reincarnated. lul

Readability is very important. It is very hard to explain shortly as agreement with that conclusion comes with experience.
With the experience also you shift amount of focus you give that single line to larger and larger forms: methods, classes, components, modules, applications, systems. The lower level the structure is the less time you want to spend writing it, andā€¦ reading it after a year or two. With the experience also comes usage of the so called ā€œdesign patternsā€.

Companies try to follow some most commonly used conventions, so their developers will be more productive, and alsoā€¦ replaceable.
There is nothing worse in software industry than reading/fixing a code written with total disregard of readability good practices and design patterns (in most cases it means that you are looking at a code of a person that was solving that kind of problem for a first time).

So for example:

if (position[x][y + 1] == 1) { numberofneighbors += 1; }

In Java, I think most of the conventions do actually force then statements to be not only in the next line but also

if (position[x][y + 1] == 1) {
       numberofneighbors += 1; 
}

But you do not want that? No problemā€¦

numberofneighbors += position[x][y + 1]==1? 1: 0;

That do not actually fix readability, nor the multi line "if " would, because as someone mentioned you forgot one case. So how not to forgot, and made intention more readable:

for (int xShift=-1; xShift<=1; xShift++ ) {
    for (int yShift=-1; yShift<=1; yShift++ ) {
       if (xShift !=0 ||  yShift!=0) {
            numberofneighbors += position[x+xShift][y + yShift]==1? 1: 0;
       }      
   }			
}

That kind of example more or less also shows that you stop thinking about only one single line / statement at a time (as a CPU or compiler does). You also actually stop being a ā€œmonkeyā€ that 8 times writes almost the same instructions accordingly to the algorithm and you actually start writing the algorithm to the compiler. And let the CPU execute it 8 times (not you).

And going furtherā€¦
Someone still can have an itch that ā€œxShift !=0 || yShift!=0ā€ do not describe it self good. And you thing that this might be a good place to put a documentation comment. However there is an concept of writing self explanatory code that can be easily applied here:

for (int xShift=-1; xShift<=1; xShift++ ) {
    for (int yShift=-1; yShift<=1; yShift++ ) {
       if ( isNeighbor(xShift, yShift) ) {
            numberofneighbors += position[x+xShift][y + yShift]==1? 1: 0;
       }      
   }			
}

private static boolean isNeighbor(xShift, yShift) {
    return xShift !=0 ||  yShift!=0;
}

Is that too much linesā€¦ yes, it is:

for (int xShift=-1; xShift<=1; xShift++ ) {
    for (int yShift=-1; yShift<=1; yShift++ ) {
       if ( IS_NEIGHBOUR.test(xShift, yShift) ) {
            numberofneighbors += position[x+xShift][y + yShift]==1? 1: 0;
       }      
   }			
}

private static final BiPredicate<Integer, Integer> IS_NEIGHBOUR = (x,y) ->  xShift !=0 ||  yShift!=0;

And that would be OK for any application with exception for low-latency and high performance applications where that boxing/unboxing of primitive values actually matters.

And lets not forget about ā€œnumberofneighborsā€: useTheCamelCase

And be good at it: rememberThatCamelCaseMeansHtmlNotHTML

Then you can actually start thinking the Object-Oriented way and enclose position array into theā€¦

Interrupting note: I think creating class for Cell not board is like telling the problem that Iā€™m solving is a GOL of one Cell and one of the tools to solve that Cell problem is to use board (while that is the other way around - you solve the problem of Board, that contains Cells - probably creation of Cell object is not needed )

ā€¦ object:

public class LiveTable {
    private boolen[][] table;  

   ...

   boolean isThereALiveInPosition(x,y) {
       return position[x][y];
   }
}

So now, our few lines of code will look like:

for (int xShift=-1; xShift<=1; xShift++ ) {
    for (int yShift=-1; yShift<=1; yShift++ ) {
       if ( IS_NEIGHBOUR.test(xShift, yShift) ) {
            numberofneighbors += liveTable.isThereALiveInPosition( x + xShift,  y + yShift ) 1: 0;
       }      
   }			
}

private static final BiPredicate<Integer, Integer> IS_NEIGHBOUR = ( x, y ) ->  xShift !=0 ||  yShift!=0;

Please note that I applied selected set of rules, on selected lines of code.

One problem I have that I cannot easily solved is to provide you good sources for all of that - as

  1. experience is the best teacher
  2. there are many sources, I simply no longer visit them :wink:
1 Like

These days Iā€™m more bothered by what I call ā€œover abstractionā€, and ā€œmake everything reusableā€, and ā€œleaky abstractionsā€.

As for shorter snippets of code, search and look for ā€œJava style guideā€ documents , and then read ā€œEffective Javaā€. Thereā€™s usually analogues for every other programming language as well.

Youā€™ll get an idea of dos and donts from there.

1 Like

Just wanna throw this in here:

https://google.github.io/styleguide/javaguide.html

Google has thrown a lot of talent behind itā€™s style guides. By all means, you donā€™t need to take it as gospel, but it is useful, at the very least, as a point of reference. Presumably, some talented, experienced (well-paid) programmers put it together.

2 Likes

This is very much an issue. Donā€™t be afraid to re-write code. Plan on it. Donā€™t drink your own Kool-aid believing youā€™ve architected the end-all-be-all API/object that solves all problems. Solve small problems and collect those solutions into a library. Understand that your solution is likely short-sighted and will need to adapt. Donā€™t overthink it.

Iā€™m a bit dumbfounded by the claim that someone teaching coding suggested that neatness didnā€™t count? If this is really the case, you should discount/ignore that person. They are wrong and should not be teaching others if that is really the case.

The ability of other people to read and understand your code is paramount to effective collaboration. You should always write your code with an eye toward ā€œdoes this make sense to someone elseā€. Opensource or not, for you to be effective, someone else has to be able to pick up where you left off. Which might be you years later.

It is also an issue for bugs - as others have pointed out, organization of computation of a given variable such that it is clear how that variable will be set to what aids in testing and debug. Think about your code form the perspective of reaching every corner case. Can you identify those cases by reading the code?

Good indentation, good editor helper macros so that styles can be enforced by them. Get used to adapting to alternate styles, every group has their own.

You can learn a lot about someone by reading their code, write it assuming it is communication with other humans as much as it is to a compiler.

I often interview people about to join the company I work with/for, and I ask them to write code, neatness definitely counts in my book. Itā€™s true we live in an age of intelligent IDEs and automatic code formatters, and by itself is pointless if you canā€™t solve the problem youā€™re being asked to solve.

Maybe @trexd took the teacher out of context.

Itā€™s also true you can go pretty far not being neat in terms of how the code looks, nor in terms of design.

My recently favorite example is from a Dissecting modern (3G/4G) cellular modems (33c3) talk, specifically the slide titled ā€œHow many processes does it take to reboot a systemā€. In this case the system is actually a pcie modem that happens to run Linux of its own.

  1. Donā€™t listen to your professor. He probably never worked on large projects or wrote useful code (code that someone else used).

  2. If you want to learn to write beautiful code, use python.