Closed. This question is opinion-based。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
                        
                        4年前关闭。
                                                                                            
                
        
我正在阅读如下的Java代码:
它在抽象类ClientEntry中定义了具体类ConfirgurationEntryLogEntry

这是一个好习惯吗?
通常,我在单独的文件中定义它们。

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