Andrew Gazelka
01/23/2019, 5:50 PMthis(...)
. However, sometimes it requires a bit of code to transform parameters to ...
. Should I...
1) have a separate function which acts as a static constructor
2) have the constructor of the class reference a functionAlan Evans
01/23/2019, 6:11 PMAlan Evans
01/23/2019, 6:14 PMDico
01/24/2019, 3:44 AMAlan Evans
01/24/2019, 12:37 PMAlan Evans
01/24/2019, 12:41 PMby
keyword also assists composition. https://proandroiddev.com/composition-over-inheritance-in-kotlin-way-fe341159bf1cAndrew Gazelka
01/27/2019, 4:20 PMabstract class BasicConfig(private val path: Path) {
fun reload(){
val configuration = YamlConfiguration.loadConfiguration(path.toFile())
process(configuration)
}
protected abstract fun process(config: ConfigurationSection)
}
Andrew Gazelka
01/27/2019, 4:20 PMAlan Evans
01/27/2019, 4:22 PMabstract
classes in any situation.Alan Evans
01/27/2019, 4:28 PMinterface ConfigurationSectionLoader {
fun load(): ConfigurationSection
}
class YamlConfigurationLoader(val path: Path) : ConfigurationSectionLoader {
override fun load(): ConfigurationSection {
return YamlConfiguration.loadConfiguration(path.toFile())
}
}
Alan Evans
01/27/2019, 4:28 PMclass YourCustomClass(private val loader: ConfigurationSectionLoader) {
fun reload() {
process(loader.load())
}
private fun process(load: ConfigurationSection) {
TODO("not implemented")
}
}
Alan Evans
01/27/2019, 4:29 PMAlan Evans
01/27/2019, 4:30 PMConfigurationSectionLoader
interface is optional. Depends how you want to couple these.Alan Evans
01/27/2019, 4:32 PMAlan Evans
01/27/2019, 4:40 PMYourCustomClass
does not need to know the path in any situation. Where as with abstract
it will always need to provide that option in it's constructor.Andrew Gazelka
01/28/2019, 2:19 AMobject PlayerSubCommand : SimpleCommand by SubCommandBase(
1,
CommandAlias("player", "p"),
PlayerTabAutocomplete,
object : SubCommandProcessor {
override fun on(sender: CommandSender, command: Command, alias: String, args: Array<out String>): SubCommandResult {
val input = args[0]
val offlinePlayer = try {
sp.server.getOfflinePlayer(UUID.fromString(input)) // UUID
} catch (e: IllegalArgumentException) {
sp.server.getOfflinePlayer(input) // name
}
return SubCommandResult.Success(
setOf(
PlayerAddGroupCommand(offlinePlayer),
PlayerRemoveGroupCommand(offlinePlayer)
)
)
}
}
)
Andrew Gazelka
01/28/2019, 2:20 AMclass SubCommandBase(
private val argsCount: Int,
private val nameable: Nameable,
private val tabCompleter: TabCompleter,
private val subCommandProcessor: SubCommandProcessor) :
SimpleCommand,
Nameable by nameable {
...
}
Alan Evans
01/28/2019, 12:36 PMTabCompleter
and arg count are SRP smells to me.Alan Evans
01/28/2019, 12:36 PMDico
01/28/2019, 1:14 PMDico
01/28/2019, 1:14 PMAlan Evans
01/28/2019, 2:08 PMDico
01/28/2019, 2:32 PMAndrew Gazelka
01/28/2019, 3:02 PMSubCommandBase
class https://gist.github.com/andrewgazelka/efb28dda2d9d5b779578c77a95d25ce0 @Alan EvansAndrew Gazelka
01/28/2019, 3:03 PMAlan Evans
01/28/2019, 4:08 PMAlan Evans
01/28/2019, 4:08 PMAlan Evans
01/28/2019, 4:10 PMDico
01/28/2019, 4:39 PMDico
01/28/2019, 4:41 PMAndrew Gazelka
01/28/2019, 5:23 PMSimpleCommand
is still an interface SubCommandBase
is just a class which combines dependencies. I don't see how this is bad...Dico
01/28/2019, 5:24 PMDico
01/28/2019, 5:25 PMAlan Evans
01/28/2019, 5:39 PMAlan Evans
01/28/2019, 5:41 PMby
here is not required:
object PlayerSubCommand : SimpleCommand = SubCommandBase(
Would work just as well wouldn't it?Dico
01/28/2019, 5:42 PMDico
01/28/2019, 5:43 PMDico
01/28/2019, 5:43 PMAlan Evans
01/28/2019, 5:45 PMval playerSubCommand : SimpleCommand = SubCommandBase(
I think it's clearer what's going on there, as with by
you might also be overriding some of the interface and I would have to look at the bottom of the declaration to find out.Alan Evans
01/28/2019, 5:55 PMvar playerSubCommand: SimpleCommand = simpleSubCommand(
1,
CommandAlias("player", "p"),
PlayerTabAutocomplete
) { args -> // none of the other crap, I don't think you should need anything but the command's arguments
{
val input = args[0]
val offlinePlayer = try {
sp.server.getOfflinePlayer(UUID.fromString(input)) // UUID
} catch (e: IllegalArgumentException) {
sp.server.getOfflinePlayer(input) // name
}
SubCommandResult.Success(
setOf(
PlayerAddGroupCommand(offlinePlayer),
PlayerRemoveGroupCommand(offlinePlayer)
)
)
}
}
Alan Evans
01/28/2019, 5:56 PMSubCommandBase
you see. SubCommandBase
should be renamed in any case though, as it is no longer a "Base" class.Alan Evans
01/28/2019, 6:01 PMvar playerSubCommand: SimpleCommand = simple2ArgSubCommand(
CommandAlias("player", "p"),
PlayerTabAutocomplete
) { arg1, arg2 ->
{
val offlinePlayer = try {
sp.server.getOfflinePlayer(UUID.fromString(arg1)) // UUID
} catch (e: IllegalArgumentException) {
sp.server.getOfflinePlayer(input) // name
}
SubCommandResult.Success(
setOf(
PlayerAddGroupCommand(offlinePlayer),
PlayerRemoveGroupCommand(offlinePlayer)
)
)
}
}
Dico
01/28/2019, 8:22 PMserver.getOfflinePlayer
can return players that don't exist. You should check that the condition it.hasPlayedBefore() || it.isOnline()
is true on the result.Dico
01/28/2019, 8:23 PMAndrew Gazelka
01/29/2019, 8:21 PMDico
01/29/2019, 9:31 PMAndrew Gazelka
01/29/2019, 9:43 PMAndrew Gazelka
01/29/2019, 9:43 PMAndrew Gazelka
02/14/2019, 2:20 AMDico
02/14/2019, 2:11 PMAlan Evans
02/14/2019, 3:20 PM