Intellij IDEA is really great but I was really frustrated by the way IDEA predicts what method to call next when building some object with setters or builder.
For example we have simple object(powered by lombok):
#Value
#Builder
public class Benefit {
private final long sourceUserId;
private final BigDecimal baseValue;
private final String multiplier;
private final int bonusId;
private final long bonusTtl;
private final String benefitId;
}
But IDEA doesn't really care that I've already called it.
It would be great to see this method on the bottom of prediction list.
Is it obvious only for me that next one in the prediction should be baseValue?
I didn't find anything about it in google and here so maybe I've just missed some basic stuff?
Is there some way to change this prediction strategy?
Related
I have class Elevator which contains base informations about Elevator itself. Like here:
#Builder
#Getter
#Setter
public class Elevator {
private final int id;
private final float maxSpeed;
private final float maxLiftingCapacity;
private float currentSpeed;
private float currentConditionFactor;
private Dimensions dimensions;
private Localization localization;
}
Now I want to separate behaviour of elevator from model, I want to create another class, maybe it will be implementing Runnable or Callable (doesn't matter now, it should be universal). It will have methods like these (prototype):
public class ElevatorRunnable implements Sleepable {
private final Elevator elevator;
public ElevatorRunnable(Elevator elevator) {
this.elevator = elevator;
}
private void moveUp() {
float posY = elevator.getLocalization().getY();
if (posY >= elevator.getBuilding().getGroundHeight()) {
elevator.getLocalization().setY(posY - elevator.getCurrentSpeed());
}
}
private void moveDown() {
float posY = elevator.getLocalization().getY();
if (posY <= elevator.getBuilding().getHeight()) {
elevator.getLocalization().setY(elevator.getLocalization().getY() + elevator.getCurrentSpeed());
}
}
I really don't think that is correct like it is now, so my question is, which pattern should I use to separate information of object from run() methods etc. Should it be Decorator?
Thank you in advance!
I think your code looks fine. The whole point is to not have state in the behavioral classes. And you don't need a design pattern for that. Well, actually, you already used one: composition.
This specific case can be overly extended since "the elevator itself moves up/down" (this means the logic will go in Elevator) or "the controller handles the movement of the elevator" in which case a Controller class can have the behavior.
Also the localization field can be discussed since the position is not actually an elevator attribute, instead it can be a controller attribute.
In some cases it can make sense to move behaviour somewhere else. In this case I think it makes more sense to keep everything in one class. An elevator has the given attributes and can move up and down. No need to make things complicated.
Also I find the name Runnable confusing. Runnable implies the class can be used to run some code. For example the interface Runnable (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runnable.html) can be extended to be run by a Thread.
I'm working with Realm to create my android app's ORM with Realm. The problem is that when I try to create an object like this:
public class Airport extends RealmObject {
private int Id;
private String Name;
private String Code;
private RealmList<Integer> destinations;
}
androidStudio tells me that I can't have the RealmList with type Integer; and for String type either.
I've been looking a few similar questions, but the best approach is to declare an object like:
public class MyRealmInteger extends RealmObject {
private int destination;
}
so this way I can rewrite my class as follows:
public class Airport extends RealmObject {
private int Id;
private String Name;
private String Code;
private RealmList<MyRealmInteger> destinations;
}
but I think it's a very complicated. There isn't any other easier solution?
but I think it's a very complicated. There isn't any other easier solution?
No there is not. Not yet at least. They're "working on it":
This feature is among a handfull of top features that we hope to take on next. We will however give the current 1.0 a bit of peace to ensure stability before we push a lot of new features.
You can check this issue for updates on it https://github.com/realm/realm-java/issues/575
Please take a look at this answer https://stackoverflow.com/a/46576569/3479489 realm will add support for primitives in the version 4.0.0
I'm aware that you could call a method from a constructor, but it could lead to problems later on if the method could be overridden. The following code is just an example I've written demonstrating my issue:
Let say I have the following subclass:
private boolean isActive;
public ChargeGun(String gameObjectID, String gameObjectName, String desc, int numberofshots, int damage, boolean isActive) {
super(gameObjectID, gameObjectName, desc, numberofshots, damage);
setAttributes(isActive);
}
public ChargeGun(String gameObjectID, String gameObjectName, int numberofshots, int damage, boolean isActive) {
super(gameObjectID, gameObjectName, numberofshots, damage);
setAttributes(isActive);
}
private final void setAttributes(boolean isActive)
{
this.isActive = isActive;
}
The boolean isActive is specific to ChargeGun and not any other gun. Given that I have two constructors in my subclass, rather than type isActive = true twice, could I call a private final method to do it? The reason is, if my attributes for ChargeGun grow, then I would have to add attributes in both constructors. If I do it with a private final method, everything is set in one place. Is this bad practice?
I can't chain the ChargeGun constructors because both call the super classes constructor.
A private method cannot be overriden, you do not also need to mark it final (which also means it cannot be overriden). Just one of final or private would be sufficient. However, the method needs to be modified slightly. Like,
private void setAttributes(boolean isActive)
{
this.isActive = isActive;
}
your version always sets it to true. If that is intentional I would remove the setter entirely, and do something like
private final boolean isActive = true;
which is a declaration and initialization of an immutable field.
If you need your setAttributes, it certainly means you have common variables to always set the same way in multiple constructors. Wouldn't it be more clear to have a "full constructor" which have all the assignment you make in setAttributes, and other shorter versions of your version calling the full version ?
Also, you really should consider using Builder pattern which clearly deals with those object that can be constructed in many different ways. If you thing it is a lot of work, just know that some plugins for IDE such as InnerBuilder make it easy to generate. If you look at how languages evolve, you will see more and more builder-like api (Stream, Optional...).
Are there any notable advantages and/or disadvantages, expecially regarding performance, to replacing
private class MyClass{
/**
* Some code here
**/
private int numberOfPeople();
private Human[] people;
private void printPeople(){
// some code here
}
/**
* Some code here
**/
}
with an inner class like this, that better encapsulates the data:
private class MyClass{
/**
* Some code here
**/
private class PeopleHandler{
private int numberOfPeople();
private Human[] people;
private void printPeople(){
// some code here
}
private void doOherStuff{
// some code here
}
}
/**
* Some code here
**/
}
I need to know this specifically for Java and Java Android.
If you replace one class with another it makes little difference.
Using a nested class is about as expensive is adding a reference to a class. It could make a difference if you have many millions, but for most use cases you will have trouble measuring the difference.
I suggest you do what you believe is simplest and easiest to understand, and this is likely to perform well enough also.
I remember a couple years ago I was using static initializers to call class-level setup operations. I remember it having very bizarre behaviors and I just decided to steer clear from them. Maybe it was because I was messing up the top-bottom order or being a newbie. But I am encountering a need to revisit them and I want to make sure there is not a better way that is just as concise.
I know it is not fashionable, but I often have data-driven classes that maintain a static list of instances imported from a database.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
When I have dozens of table-driven classes like this one, this pattern is very concise (yes I know it tightly couples the class with one source of data/instances).
However, when I discovered the goodness of Google Guava I want to use the EventBus to update the static list when a certain event posted. I would create a static final boolean variable just to call a static method that initialized the registration.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private static final boolean subscribed = subscribe();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
private static boolean subscribe() {
MyEventBus.get().register(new Object() {
#Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
return true;
}
}
This got annoying very quickly, because the compiler would throw warnings over the subscribed variable never being used. Also, it just added clutter. So I'm wondering if it is kosher to use the static initializer, and there really is no better way if I do not decouple this into two or more classes. Thoughts?
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
static {
MyEventBus.get().register(new Object() {
#Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
}
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
So I'm wondering if it is kosher to use the static initializer
The funny thing is that
private static final boolean subscribed = subscribe();
and
private static final boolean subscribed;
static {
subscribed = subscribe();
}
get compiled to exactly the same bytecode. So using the needless static variable is strictly worse.
But until we are ready to scale up to a DI-driven framework,
Discover Guice. Don't call it framework (though it is). It's easy to use and let's you get rid of static.
Or do it manually. Rewrite your class by dropping all static modifiers and pass it everywhere you need it. It's rather verbose sometimes, but stating dependencies explicitly allows you to test classes in isolation.
The way it is, you can't test StratBand without hitting the database, no matter how trivial the method under test is. The problem is the coupling of every StratBand instance to the list of all StratBands.
Moreover, you can't test the behavior dependent on the stratBands contents as it always get loaded from the DB (sure, you can fill your DB correspondingly, but it's a big pain).
For starters, I'd create StratBandManager (or StratBands or whatever name you like) and move all the static functionality to it. In order to easy the transition, I'd create a temporary class with static helpers like
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
return stratBandManager.stratBands();
}
Then deprecate it all and replace it by DI (using Guice or doing it manually).
I find Guice useful even for small projects. The overhead is tiny as often there's no or hardly any configuration.