Last active
August 27, 2024 10:58
-
-
Save yegor256/6335539 to your computer and use it in GitHub Desktop.
quiz.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Please review the class below and suggest improvements. How would | |
* you refactor this class if it would be in a real-life project? | |
* There are many problems here, both high-level design mistakes, | |
* and low-level implementation bugs. We're interested to see high-level | |
* problems first, since they are most critical. The more mistakes | |
* you can spot, the better programmer you are. | |
*/ | |
/** | |
* This class is thread safe. | |
*/ | |
public class Parser { | |
private File file; | |
public synchronized void setFile(File f) { | |
file = f; | |
} | |
public synchronized File getFile() { | |
return file; | |
} | |
public String getContent() throws IOException { | |
InputStream i = new FileInputStream(file); | |
String output = ""; | |
int data; | |
while ((data = i.read()) > 0) { | |
output += (char) data; | |
} | |
return output; | |
} | |
public String getContentWithoutUnicode() throws IOException { | |
InputStream i = new FileInputStream(file); | |
String output = ""; | |
int data; | |
while ((data = i.read()) > 0) { | |
if (data < 0x80) { | |
output += (char) data; | |
} | |
} | |
return output; | |
} | |
public void saveContent(String content) throws IOException { | |
OutputStream o = new FileOutputStream(file); | |
for (int i = 0; i < content.length(); i += 1) { | |
o.write(content.charAt(i)); | |
} | |
} | |
} |
Я бы использовал библиотеку apache commons, кода станет в разы меньше:
public String getContent() throws IOException, FileNotFoundException {
if (file.exists()) {
List<String> lines = FileUtils.readLines(file, "UTF-8");
return lines.toString();
} else {
throw new FileNotFoundException("File not found...");
}
}
/**
* Made this class fully public for next extend cases
* For now it's unclear is this need to split FileContent class to different ones
*
* F.e. ParsedFile could have two methods returning SimpleContent and UnicodeFreeContent
* And each *Content class could have unique logic in it
*
* ParsedFile is thread safe because of immutability
*/
class FileContent {
private final String raw;
public FileContent(String rawContent) {
this.raw = rawContent;
}
public String text() {
return this.raw;
}
}
class ParsedFile {
private final InputStream fileInputStream;
public ParsedFile(InputStream fileInputStream) {
this.fileInputStream = fileInputStream;
}
public FileContent content() {
String content = "bytes converted to string";
return new FileContent(content);
}
public FileContent contentUnicodeFree() {
String content = "bytes converted to string without unicode";
return new FileContent(content);
}
}
class DefaultParsedFileUsage {
public static void main(String[] args) {
File file = new File("path");
try(InputStream is = new FileInputStream(file)) {
ParsedFile parsedFile = new ParsedFile(is);
FileContent fileContent = parsedFile.content();
String fileText = fileContent.text();
// next code
} catch (IOException ioException) {
// logging exception
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
High-level design issues:
Read from the file:
String content = new String(Files.readAllBytes(Paths.get(fileName)));
Write to new file (note, this functionality should not be in parser entity):
Files.write(Paths.get(fileName), content.getBytes(), StandardOpenOption.CREATE);
If the Files interface is too complicated for client class a new helping util class with simplificated interface can be implemented to hide Files usage:
I prefer to define such a member instead of current setFile(File) and subsequent call of getContent():
public synchronized String getContent(java.net.URI uri)
Also this is better to use singleton pattern to not create many instances for such a utility class.
The method getContent handles only ASCII symbols.
The method getContentWithoutUnicode() is written invalid if it is intended to exclude unicode symbols. InputStream.read() returns only 1 next byte from the stream, so for typical unicode symbol we will exclude only first byte of symbol value. So only unicode symbols from range 0x80 – 0xFF will be excluded correctly.
Also there are can be issues with characters encoding (UTF8 , UTF16)
Low-level issues