At this article I would tell about about one important code quality – maintenance.
- Problem.
- Two ways to solve your technical debt.
- Statick methods
- Getters and setter
- Avoid null.
- Conclusion.
Problem
In a technical world exists such fact as technical debt. It looks like we must devote time to improving maintainable code base of our product. For example, we work on the Android App. We must deliver app to the end customer as soon as possible. But it comes time, when you already do not understand what is going on in the app, there are many dependencies or redundant if – else blocks, while it is possible to make some things simpler. So to devote time to improving your code base may be a good decision. First of all, personally for you – you’ll be grateful to yourself for this while others will be grateful to you for this too. Recently I’ve read “Effective Java” by Joshua Bloch, and “Elegant Objects” by Yegor Bugaenko. These two books are opposite to each other.
Two ways to solve your technical debt
Static methods
Joshua Bloch – static method it is good, it may uses instead constructor. For example:
public class Car {//Client of this does not may create object by this way. Only staticprivate Car() {}//Create a default car for client.public static Car getDefaultCar() {return new Car();}}public class Car { //Client of this does not may create object by this way. Only static private Car() { } //Create a default car for client. public static Car getDefaultCar() { return new Car(); } }public class Car { //Client of this does not may create object by this way. Only static private Car() { } //Create a default car for client. public static Car getDefaultCar() { return new Car(); } }
Instead it Elegant Object says us:
Static methods is evil, do not use it! But if your procedural programmer you may use it:)
Getters and setter
For many years we’ve considered getter and setter methods to be the encapsulation of the object state. But it is not true. We may influence on this internal state by setter methods. For example:
public class Cash {private int dollars;public Cash(int dollars) {this.dollars = dollars;}//Influence on the internal state on the objectpublic void setDollars(int dollars) {this.dollars = dollars;}public int getDollars() {return this.dollars;}}public class Cash { private int dollars; public Cash(int dollars) { this.dollars = dollars; } //Influence on the internal state on the object public void setDollars(int dollars) { this.dollars = dollars; } public int getDollars() { return this.dollars; } }public class Cash { private int dollars; public Cash(int dollars) { this.dollars = dollars; } //Influence on the internal state on the object public void setDollars(int dollars) { this.dollars = dollars; } public int getDollars() { return this.dollars; } }
t is not a good method to have mutable object, much better is to have immutable object such as java.lang.String
public class Cash {private final Integer dollars;public Cash(final Integer dollars) {this.dollars = dollars;}public Integer usd() {return this.dollars;}}public class Cash { private final Integer dollars; public Cash(final Integer dollars) { this.dollars = dollars; } public Integer usd() { return this.dollars; } }public class Cash { private final Integer dollars; public Cash(final Integer dollars) { this.dollars = dollars; } public Integer usd() { return this.dollars; } }
In this case we don’t have an opportunity to change internal state of the object. To present a new cash we must create a new object.
Avoid null
Sometimes you have method which takes null
as argument. For example:
public class FileFinder {private final File file;public FileFinder(final File file) {this.file = file;}public List<String> findByMask(IMask mask) {if (mask == null) {return mask.all();}return mask.find(file);}public static void main(String[] args) {IMask mskMask = new Mask("*.msk");List<String> mskFiles = new FileFinder(args[0]).find(mskMask);//Get all filesList<String> allFiles = new FileFinder(args[0]).find(null);}}public class FileFinder { private final File file; public FileFinder(final File file) { this.file = file; } public List<String> findByMask(IMask mask) { if (mask == null) { return mask.all(); } return mask.find(file); } public static void main(String[] args) { IMask mskMask = new Mask("*.msk"); List<String> mskFiles = new FileFinder(args[0]).find(mskMask); //Get all files List<String> allFiles = new FileFinder(args[0]).find(null); } }public class FileFinder { private final File file; public FileFinder(final File file) { this.file = file; } public List<String> findByMask(IMask mask) { if (mask == null) { return mask.all(); } return mask.find(file); } public static void main(String[] args) { IMask mskMask = new Mask("*.msk"); List<String> mskFiles = new FileFinder(args[0]).find(mskMask); //Get all files List<String> allFiles = new FileFinder(args[0]).find(null); } }
This code looks correct, but it has many useless words. Do not use null, use a stub object. With stub object the code above will look in the following way:
public class FileFinder {private final File file;public FileFinder(final File file) {this.file = file;}public List<String> findByMask(IMask mask) {return mask.find(file);}public static void main(String[] args) {IMask withouAnyMask = new WithoutAnyMaskImpl();List<String> allFiles = new FileFinder(args[0]).find(withoutAnyMask);}}public class FileFinder { private final File file; public FileFinder(final File file) { this.file = file; } public List<String> findByMask(IMask mask) { return mask.find(file); } public static void main(String[] args) { IMask withouAnyMask = new WithoutAnyMaskImpl(); List<String> allFiles = new FileFinder(args[0]).find(withoutAnyMask); } }public class FileFinder { private final File file; public FileFinder(final File file) { this.file = file; } public List<String> findByMask(IMask mask) { return mask.find(file); } public static void main(String[] args) { IMask withouAnyMask = new WithoutAnyMaskImpl(); List<String> allFiles = new FileFinder(args[0]).find(withoutAnyMask); } }
For me personally the second option is more readable and understandable. Also it does not produce ugly NullPointerException
.
Conclusion
I suggest reading both books to have a deeper understanding of how to improve the code quality. Also I recommend thinking about maintainability of your code base, because it is really important.
Follow me 😉
原文链接:Technical debt or we must improve our code base quality
暂无评论内容