Closed. This question is opinion-based。它当前不接受答案。
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
4年前关闭。
我正在阅读如下的Java代码:
它在抽象类
这是一个好习惯吗?
通常,我在单独的文件中定义它们。
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
4年前关闭。
我正在阅读如下的Java代码:
它在抽象类
ClientEntry
中定义了具体类ConfirgurationEntry
,LogEntry
。这是一个好习惯吗?
通常,我在单独的文件中定义它们。
public abstract class LogEntry {
/**
* The four allowed {@link LogEntry} types.
*/
public static enum Type {
/**
* {@link LogEntry} with {@code index} = 0, {@code term} = 0.
*/
SENTINEL,
/**
* {@link LogEntry} that stores a noop entry.
*/
NOOP,
/**
* {@link LogEntry} that stores cluster membership information about the Raft cluster.
*/
CONFIGURATION,
/**
* {@link LogEntry} that stores a {@link Command} submitted by a client.
*/
CLIENT,
}
/**
* Singleton instance of the {@link LogEntry.Type#SENTINEL} log entry.
*/
public static final LogEntry SENTINEL = new LogEntry(Type.SENTINEL, 0, 0) {
@Override
public String toString() {
return Objects
.toStringHelper(this)
.add("type", "SENTINEL")
.add("index", getIndex())
.add("term", getTerm())
.toString();
}
};
//----------------------------------------------------------------------------------------------------------------//
//
// Base class
//
private final Type type;
private final long index;
private final long term;
// keeping this constructor private restricts
// the number of allowed LogEntry types to those defined in this
// compilation unit
// i.e. using 'protected' instead would allow anyone to define additional
// LogEntry types, which I don't support
private LogEntry(Type type, long index, long term) {
checkArgument(index >= 0, "index must be positive:%s", index);
checkArgument(term >= 0, "term must be positive:%s", term);
if (index == 0 && term == 0) {
checkArgument(type == Type.SENTINEL);
}
this.type = type;
this.index = index;
this.term = term;
}
/**
* Get the type of this log entry.
*
* @return {@link LogEntry.Type} of this log entry
*/
public final Type getType() {
return type;
}
/**
* Get the log entry's position in the 0-indexed Raft log.
*
* @return index >= 0 of this log entry's position in the Raft log
*/
public long getIndex() {
return index;
}
/**
* Get the election term in which this log entry was created.
*
* @return election term >= 0 in which this log entry was created
*/
public final long getTerm() {
return term;
}
@Override
public int hashCode() {
return Objects.hashCode(type, index, term);
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LogEntry other = (LogEntry) o;
return type == other.type && index == other.index && term == other.term;
}
//----------------------------------------------------------------------------------------------------------------//
//
// Subclasses
//
/**
* {@code LogEntry} that contains a client {@link Command}.
* <p/>
* Once this entry is committed
* the client is notified via {@link io.libraft.RaftListener#applyCommitted(Committed)}
* that this {@code Command} can be applied locally.
*/
public static final class ClientEntry extends LogEntry {
private final Command command;
/**
* Constructor.
*
* @param index index > 0 of this log entry's position in the log
* @param term election term > 0 in which this log entry was created
* @param command instance of {@link Command} to be replicated
*/
public ClientEntry(long index, long term, Command command) {
super(Type.CLIENT, index, term);
this.command = command;
}
/**
* Get the {@link Command} to be replicated.
*
* @return instance of {@code Command} to be replicated
*/
public Command getCommand() {
return command;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientEntry other = (ClientEntry) o;
return getType() == other.getType()
&& getIndex() == other.getIndex()
&& getTerm() == other.getTerm()
&& command.equals(other.command);
}
@Override
public int hashCode() {
return Objects.hashCode(getType(), getIndex(), getTerm(), command);
}
@Override
public String toString() {
return Objects
.toStringHelper(this)
.add("type", getType())
.add("index", getIndex())
.add("term", getTerm())
.add("command", command)
.toString();
}
}
// FIXME (AG): the design of this log entry is incorrect and has to be reworked
/**
* {@code LogEntry} that contains the
* configuration state of the Raft cluster.
*/
public static final class ConfigurationEntry extends LogEntry {
private final Set<String> oldConfiguration;
private final Set<String> newConfiguration;
/**
* Constructor.
*
* @param index index > 0 of this log entry's position in the log
* @param term election term > 0 in which this log entry was created
*/
public ConfigurationEntry(long index, long term, Set<String> oldConfiguration, Set<String> newConfiguration) {
super(Type.CONFIGURATION, index, term);
this.oldConfiguration = oldConfiguration;
this.newConfiguration = newConfiguration;
}
public Set<String> getOldConfiguration() {
return oldConfiguration;
}
public Set<String> getNewConfiguration() {
return newConfiguration;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ConfigurationEntry other = (ConfigurationEntry) o;
return getType() == other.getType()
&& getIndex() == other.getIndex()
&& getTerm() == other.getTerm()
&& oldConfiguration.equals(other.oldConfiguration)
&& newConfiguration.equals(other.newConfiguration);
}
@Override
public int hashCode() {
return Objects.hashCode(getType(), getIndex(), getTerm(), oldConfiguration, newConfiguration);
}
@Override
public String toString() {
return Objects
.toStringHelper(this)
.add("type", getType())
.add("index", getIndex())
.add("term", getTerm())
.add("oldConfiguration", oldConfiguration)
.add("newConfiguration", newConfiguration)
.toString();
}
}
/**
* noop {@code LogEntry}.
* <p/>
* {@code NoopEntry} is for {@link RaftAlgorithm}
* internal use only. The client <strong>will not</strong>
* be notified when a {@code NoopEntry} instance
* is committed.
*/
public static final class NoopEntry extends LogEntry {
/**
* Constructor.
*
* @param index index > 0 of this log entry's position in the log
* @param term election term > 0 in which this log entry was created
*/
public NoopEntry(long index, long term) {
super(Type.NOOP, index, term);
}
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("type", getType())
.add("index", getIndex())
.add("term", getTerm())
.toString();
}
}
最佳答案
老实说如果我在工作中这样做,老板可能会在我的机器上拿个喷灯。但这仅仅是因为我的工作场所内的编码约定。
引用著名的乔恩·斯基特
我为这项技术建议的名称(在一个源文件中包含多个顶级类)将是“ mess”。严重的是,我认为这不是一个好主意-在这种情况下,我将使用嵌套类型。然后,仍然很容易预测它所在的源文件。但是我不相信这种方法有正式的术语。
传统的观点是每个文件都遵循一个类,特别是如果您要添加遵循该模式的现有代码库时。编译器不禁止使用它,但也不是:
int x = 4;
int y = (4 * x * 6 * x * 10 * x * 56 * x);
String s = "s" + "t" + "r" + "i" + "n" + "g";
08-26 09:35