4
\$\begingroup\$

I have written a simple program in Java 7 to write the .gitignore of different file types:

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Scanner;


public class Oye {
    private static final String HELP_TXT = "help.txt";
    private static final String DATA = "gitignore";
    private HashMap<String, String> map = new HashMap<String, String>();

    public Oye() {
    // Eager approach, building the map in the constructor. Is it good?
        File file = new File(DATA);
        if (file.exists()) {
          if (file.isDirectory()) {
              findFiles(file.listFiles());
          }
      } else {
        println("No data folder: " + DATA);
      }
    }

public static void main(String[] args) {
    if (args.length == 0) {
      printFile(HELP_TXT);
      return;
    }

    Oye oye = new Oye();
    if (args[0].equals("ls")) {
        oye.listFiles();
    } else {
        printFile(oye.getFilePath(args[0]));
    }
}

public void findFiles(File[] files) {
    for (File file: files) {
        if (file.isDirectory()) {
            findFiles(file.listFiles());
        } else {
            String fileName = file.getName();
            if (fileName.endsWith(".gitignore")) {
                fileName = fileName.substring(0, fileName.indexOf(".gitignore"));
                map.put(fileName, file.getAbsolutePath());
            }
        }
    }
}

private String getFilePath(String name) {
    if (map.containsKey(name)) {
      return map.get(name);
    } else {
      throw new IllegalArgumentException("No such file: " + name);
    }
}

private static void printFile(String path) {
    Scanner scanner = null;
    try {
        scanner = new Scanner(new File(path));
        String line;
        while (scanner.hasNextLine()) {
            println(scanner.nextLine());
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        scanner.close();
    }
}

private static void println(String txt) {
  System.out.println(txt);
}

private void listFiles() {
    for (String key: map.keySet()) {
        println(key);
    }
}
}

I know that this code is written in a very naive manner, but I want to know how I can improve my code, specifically about better design decisions and better error handling (should I have my own error classes?).

Assumptions:

  • Any single .gitignore file can't be more than few hundred lines.
  • .gitignore directory contains all the content and isn't deeply nested.
\$\endgroup\$
5
  • 1
    \$\begingroup\$ File system access in the constructor... ouch \$\endgroup\$
    – Dan
    Commented Aug 18, 2015 at 10:51
  • \$\begingroup\$ @Dan pls let me know why it hurts? \$\endgroup\$
    – CodeYogi
    Commented Aug 18, 2015 at 15:35
  • \$\begingroup\$ I was originally writing a review, but I stopped half way through because I felt it was becoming more of a code rewrite. You can find the in-progress here gist.github.com/danpantry/fa7bb445481b6fe05bc2 \$\endgroup\$
    – Dan
    Commented Aug 18, 2015 at 15:36
  • \$\begingroup\$ @Dan interesting! I was thinking same that how painful it will be for me to edit code again and again here :) \$\endgroup\$
    – CodeYogi
    Commented Aug 18, 2015 at 15:37
  • \$\begingroup\$ For the proper context I am making the clone of this app in java. \$\endgroup\$
    – CodeYogi
    Commented Aug 18, 2015 at 15:41

2 Answers 2

4
\$\begingroup\$

Printing or writing .gitignore files?

Your title says printing, your description says writing, and your code seem to indicate you are merely creating a Map of directory, which has a .gitignore file, to the actual path of the file itself.

Class name

Oye is an unconventional choice for a Java class whose functionality is to display the contents of .gitignore files. Correct me if it actually means that in some foreign language. :)

Directory traversal in Java 7

Pardon my knee-jerk 'are you on Java 8' comment-questions (at least until Java 9 comes out next year...), but you don't have to be on the latest version, at time of writing, to implement the right directory traversal code. It's already made available in Java 7, do look at this quick write-up and the relevant FileVisitor interface. In my opinion, this should be one of the few classes in your simple Java application, you probably do not even require an instance of your Oye class.

Simplification

private static void println(String txt) {
    System.out.println(txt);
}

This method is unfortunately wholly redundant... You should just simply use System.out.println() for now. Remember, you aren't gonna need it. ;)

private static void printFile(String path) {
    // ...
}

Hmms... this entire method can, and should be, replaced by Files.readAllLines(Path, Charset) too...

\$\endgroup\$
5
  • 1
    \$\begingroup\$ In java 8, more idiomatic than a FileVisitor may be to use Files.find \$\endgroup\$
    – Vogel612
    Commented Aug 18, 2015 at 21:50
  • \$\begingroup\$ Hi, I didn't use Files because I wanted to minimize the dependency on extra classes, wdyt? \$\endgroup\$
    – CodeYogi
    Commented Aug 19, 2015 at 4:45
  • \$\begingroup\$ @h.j.k, for the proper context I am making the clone of this app in java. \$\endgroup\$
    – CodeYogi
    Commented Aug 19, 2015 at 4:48
  • \$\begingroup\$ @h.j.k, I used printFile so that the user can see the content in the console or can redirect the o/p to a file for later use. \$\endgroup\$
    – CodeYogi
    Commented Aug 19, 2015 at 4:50
  • 1
    \$\begingroup\$ @CodeYogi Files is part of Java 7, so it's not like you need to put extra JAR files on your classpath when you run your Java application if this is what you are trying to avoid... I hope that answers your question. As for printFile(), you don't need to manually spin up a Scanner to read line-by-line, Files.readAllLines(Path, Charset) gives you the entire content in a List, and then you're free to do whatever you want with the List instance. \$\endgroup\$
    – h.j.k.
    Commented Aug 19, 2015 at 6:17
4
\$\begingroup\$

A few points that could be improved:

  • HELP_TXT: is it really worth readability to slim down your code down by a few bytes? HELP_TEXT is better.
    • Same with println's parameter: String txt \$\rightarrow\$ String text
  • Oye oye = new Oye(): Sounds like a stereotypical Australian day, if this is the name of your script, perhaps consider a name change. GIT_IGNORER works wonders in the understanding department.
  • fileName.substring(0, fileName.indexOf(".gitignore")): there's a magical tool called .replace: filename = filename.replace('.gitignore', '')
  • line is redundant and unused:

    try {
        scanner = new Scanner(new File(path));
        String line;
        while (scanner.hasNextLine()) {
            println(scanner.nextLine());
        }
    
\$\endgroup\$
0

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.