Amazing Java programming (let's stop)

Introduction

There is the word "principle of least astonishment".

To quote a Wikipedia article http://ja.wikipedia.org/wiki/%E9%A9%9A%E3%81%8D%E6%9C%80%E5%B0%8F%E3%81%AE%E5%8E%9F%E5%89%87

In the design and ergonomics of user interfaces and programming languages, when the two elements of an interface are inconsistent or unclear, the behavior that seems most natural (less surprising) to human users and programmers is The idea is that you should choose.

In short, it is better to have less surprises when using it [1]. [1]: There are quite a lot of situations where I'm wondering which one is less surprising ...

In this article, I will dare to introduce how to write a surprising ** many ** programs. Experience what it feels like to read a surprising program. Of course, it's better to write a program that is less surprising, so don't copy it, right?

Surprise with coding

Non-camel case

In Java, it is common to use camel case (excluding constants). If you break it, everyone will be surprised.

public class db_manager {
    private String connection_url;
    
    public void Init(){
・ ・ ・
    }
・ ・ ・
}

Serial number name

Thoroughly manage class names, method names, and even field names to create serial numbers. The impact that the contents cannot be imagined from the name is quite large.

public class UC8010 extends CMN0101 {
    private String FLD0001;
    
    public int MTD0001() {
・ ・ ・
    }
・ ・ ・
}
publi class UC8020 extends CMN0101 {
    private String FLD0001;
    
    public int MTD0001() {
・ ・ ・
    }
・ ・ ・
}

flag

Everyone is surprised if the name of the flag contains a value other than true, false or 0,1.

String modeFlag = getFlag();
switch(modeFlag) {
    case "LOGIN":
・ ・ ・
    case "LOGOFF"
・ ・ ・
}

It's also a good idea to reverse the name and behavior of the flag.

if (skipFlag == true) {
    execute();
}

Do something that isn't in the name

Let's do things that are not written in the name. The example below is a method that pretends to be a method that checks the value, and if the result is OK, the subsequent processing is also advanced. Are you surprised?

boolean checkValue(int value) {
   if (value == -1) {
      return false;
   }
   execute(value);
   return true;
}

Names that are unlikely to be relevant

If you have an interface called IFHoge and a class called Hoge, I think everyone is Hoge implements IFHoge. It's fun just to imagine the other person's face when betrayed there.

public interface IFHoge {
    void someMethod()
}
public class Hoge {
   //It has nothing to do with IFHoge
}

Write a comment that you can see

If you add a comment to the self-explanatory process, you will be surprised at how polite it is.

int time = endTime - startTime; //endTime to time-Substitute startTime

Japanese translation comment of the name

It's too common to write in a comment what it's doing, what it's meant to be, what precautions to take, and so on. Therefore, let's concentrate on the Japanese translation of the name in the comments. I am surprised that "I haven't written anything I want to know!"

/*
 *Value check
 */
booelan checkValue() {
・ ・ ・
}

Lie comment

Obviously, I'm surprised that what I say in the comments is different from what I'm actually doing.

There is no trick to tell a lie openly with new code. The opportunity is when the system is refurbished. When you rewrite the source code, leave the comments of the original source as they are without updating them. Comments and processing will be separated in a blink of an eye.

if (mode == STANDBY) {
   //In standby mode, do nothing and return immediately
   standbyService.execute();
}

Wide scope

In order to surprise many people, the story will not start unless many people see it. Let's actively use public. The wider the scope, the better.

public void publicMethod() {
    innerMethod();
}

public void innerMethod() {
    //Something processing
}

If you have a chance to inherit some class, it would be nice to raise all the visibility of the method to public.

Use what you can use

On the contrary, if you can use something that you shouldn't use at first glance, use it. Let's actively use it even with private APIs and Deprecated classes and methods. It's a waste. The author is amazed at how it is used unexpectedly.

 sun.misc.BASE64Encoder e = new sun.misc.BASE64Encoder();
 String encoded = e.encode(buf);

reflection

Well-designed code is well-encapsulated and may not be touched on its own. So it's reflection. It is no exaggeration to say that reflection exists to surprise people except for serious situations such as framework creation.

Class c = obj.getClass();
Field f = c.getField("counter");
f.setInt(obj, 0);   //Reset the counter to zero

Inheritance that is not is-a

Depending on how you use inheritance, you will be very surprised.

For example, suppose that DB processing is abstracted as DBStrategy in order to switch processing depending on the type of DB. Processing of each DB is performed by implementing this interface.

interface DBStrategy {
・ ・ ・
}
class MySQLStrategy implements DBStrategy {
・ ・ ・
}
class SQLServerStrategy implements DBStrategy {
・ ・ ・
}

After implementing it, I noticed that MySQL Strategy and SQL Server Strategy have many similar processes.

In such a case, let's create a SQL Server Strategy that inherits MySQL Strategy like this and program only the difference. Everyone thinks "that !?" It's not "SQL Server is MySQL".

interface DBStrategy {
・ ・ ・
}
class MySQLStrategy implements DBStrategy {
・ ・ ・
}
class SQLServerStrategy extends MySQLStrategy  {
・ ・ ・
}

You won't be surprised if you write it straight as below.

interface DBStrategy {
・ ・ ・
}
abstract class AbstractDbStrategy implements DBStrategy {
・ ・ ・
}
class MySQLStrategy extends AbstractDbStrategy {
・ ・ ・
}
class SQLServerStrategy extends AbstractDbStrategy {
・ ・ ・
}

Downcast

If you want a concrete class, let's actively downcast. Of course, it is better not to perform type inspection as much as possible. Also, there is no need to redesign. Later, some people will be surprised that they cannot switch the concrete class.

public void execute(DBStrategy strategy) {
    MySQLStrategy mySqlStrategy = (MySQLStrategy)strategy;
・ ・ ・
}

Dense dependence

Let's actively depend on other classes. The more complicated it is, the better. If you mess with this, it will break, and you can't fix it depending on it. No test. If you don't insist that much, you won't be surprised.

Crushing exceptions

Here are the basics of the basics. It is no exaggeration to say that if you want to surprise people, start from here. The resulting system behaves strangely and surprises the user, and the operator is also surprised because it is difficult to debug because the bad location cannot be identified.

try {
    someService.execute();
} (SomeServiceException e) {
    //I'm not sure, so squeeze it
}

Throw away the underlying exception

There is a slightly more advanced way to throw away the underlying exception. When you catch an exception, convert it to another exception, and throw it higher, let's throw away the underlying exception.

try {
    someService.execute();
} (SomeServiceException e) {
    throw new SystemException();
    // throw new SystemException(e); //← This is not surprising
}

If you do this, you won't see the underlying exception in the log when something goes wrong, so you can't follow it anymore. People who debug are very surprised.

Catch exceptions that should not be handled

There are exceptions that occur as a result of coding mistakes. A typical example is NullPointerException. It's a good rule to code these exceptions so that they don't occur in the first place, but let's catch them and handle them. There are a lot of people who are surprised because the discovery of strange situations is delayed.

try {
    someService.execute();
} catch(NullPointerException e) {
    //Let me recover
}

Make it as good as possible

Give the object as much state as possible. Isn't it interesting to have a world where the same result is guaranteed every time you call?

Ignore hash code requirements

In Java, if you override the Object # equals () method, you must also override the Object # hashCode () method correctly. This is a requirement for using Hashtable and HashMap. I don't plan to put this class in HashMap, so if you think you should, ignore it. The day will come when you will be surprised, "Huh? Did you put it in the HashMap? It doesn't work!"

Surprise in the test

No automated testing

It's now commonplace to do automated testing with tools like JUnit and Selenium. Project members will be surprised if they don't do these things.

100% coverage

If you really want to do automated testing, be sure to aim for 100% test coverage. Members will be surprised at the goal itself, and you will be surprised at the quality not improved because you will be forced to write tests just for coverage.

Surprise with management

Hide the code you wrote as little as possible

Showing the code to others means giving more information. In order to maximize the surprise of the other party, it should be issued at this time without giving prior information. For that reason, try to minimize the chances of showing your code to others.

History management manually

Keep your old sources in the date folder. Of course, comment out the modified part of the source code and leave it in the source, and add the date and company name / name.

When you see this, you can get a surprising experience as if you suddenly slipped back in time to the Edo period.

Build manually

Build is done manually. If you make a mistake, don't automate it. It's better not to create a build procedure if allowed. To finish off, it's best to put a jar of unknown origin into the lib folder. The successor will be surprised.


References


Finally a little snake foot

Originally, this article started with the following sentence under the name "Amazing Java Programming".

Mere programming is boring. I want to do something that surprises everyone. A collection of miscellaneous tips that can be used in such cases.

Thankfully, it was read by more people than I had imagined, and many people said it was interesting.

On the other hand, some people said, "I opened this article hoping for a way to really surprise it, but I was disappointed" and "I'm worried if anyone will really receive it." In other words, it was a boomerang state that the article itself, which tried to appeal to the "principle of least surprise", contained surprises. Tohoho ...

I thought that the state was ironic and interesting, but I wanted to clearly insist on the "principle of least surprise", so I made it the current format.

Recommended Posts

Amazing Java programming (let's stop)
Let's study Java
java programming basics
java Generic Programming
Let's touch on Java
Constraint programming in Java
Java programming basics practice-array
Java programming (class method)
Let's scrape with Java! !!
Java programming (class structure)
All about Java programming
java competitive programming memo
Java Programming Thread Runnable
Let's experiment with Java inlining
Java programming (variables and data)
Let's operate Excel with Java! !!
Java Development Basics-Practice ③ Advanced Programming-
Java programming basics practice-for statement
Java programming basics practice-switch statement
[Java] Basic terms in programming
Let's get started with parallel programming
Competitive programming private cheat sheet (Java)
Let's use Twilio in Java! (Introduction)
Java Functional Programming Exercise Book --zipWith-
Introduction to Functional Programming (Java, Javascript)
[Complete programming] §3 Let's calculate using Ruby!
Summary of object-oriented programming using Java
Let's think about what declarative programming is in Java and Elm (Part 1)