Is it better to duplicate an object to store old values? - java

I have a page where I can edit an object's values in Java. However, I would need to store and pass the object's old values as well for the Stored Procedure.
For this, I duplicated the object like so:
public void onClickEdit(Education e) {
Education edOld = new Education(e);
Education edNew = new Education(e);
goToPage(a);
}
I also made it so that the user will only edit edNew in the edit page.
The Education class has a constructor that sets another Education class' attributes as its own, like so:
public class Education {
private int educationID;
private String educationName;
private String educationStatus;
public Education() { }
public Education(Education e) {
educationID = e.getEducationID();
educationName = e.getEducationName();
educationStatus = e.getEducationStatus();
}
// setter-getters ...
}
My question is, would it be better on the memory to have a single class that has attributes for new and old attributes - like this:
private int educationID;
private String educationName;
private String educationStatus;
private int old_educationID;
private String old_educationName;
private String old_educationStatus;
or is the way that I am doing it fine as well?

Related

How to implement read and write methods of Chronicle Map SizedWriter and SizedReader interfaces for class with string member

I have created a simple class:
public class Example
{
private String name;
private int age;
// With getters and setters.
}
that I would like "put" into a chronicle map:
ChronicleMap<String,Example> map = ChronicleMapBuilder
.of(String.class, Example.class)
.name("example-map")
.entries(5_000)
.averageValue(new Example())
.valueMarshaller(ExampleSerializer.getInstance())
.averageKey("Horatio")
.createPersistedTo(new File("../logs/example.txt"));
However, I do not fully understand how to implement the ExampleSerializer class because I am not sure how the string member variables should be handled. How do I size strings? In the read and write methods, how do I read the string member variable, and how do I write the string member variable respectively. Pls note that on average, the name member string length will be between 7-10 characters. I have created the serializer below:
public class ExampleSerializer implements SizedReader<Example>,SizedWriter<Example>
{
private static ExampleSerializer INSTANCE = new ExampleSerializer();
public static ExampleSerializer getInstance() { return INSTANCE; }
private ExampleSerializer() {}
#NotNull
#Override
public Example read(Bytes in, long size, #Nullable Example using)
{
if (using == null)
using = new Example();
using.setAge(in.readInt());
using.setName(in.readUtf8()); // NOT SURE IF THIS IS CORRECT FOR A STRING
return using;
}
#Override
public long size(#NotNull Example toWrite)
{
return Integer.BYTES + ???; // NOT SURE WHAT THE SIZE SHOULD BE FOR STRING MEMBER?
}
#Override
public void write(Bytes out, long size, #NotNull Example toWrite)
{
out.writeInt(toWrite.getAge());
out.writeUtf8(toWrite.getName()); // NOT SURE IF THIS IS CORRECT FOR A STRING
}
}

Setting an instance variable using dependency

I am working on a project where I am trying to represent a Stock Portfolio. There is a class called Position. Also, there is another class called Portfolio and it's basically represents a set of positions along with additional instance variables/methods.
A single Position is stored in a plain .txt file. In order to read that file, I've created another class: ReaderService. In this class, necessary I/O operations are being performed and in the end, a List<Position> is being returned by the method called readPositions().
Portfolio class depends on ReaderService in order to set its positions field, and I am injecting that dependency via constructor, that is constructor injection.
What I can't be sure about is that it seems like a bad practice to initialize a instance variable of Portfolio class in a setter method by using ReaderService dependency. Does this approach leads to any problems like tight coupling or smt else?
Here is the quick summary
ReaderService:
public class ReaderService {
// necessary fields..
// a method to extract all positions from the each line of .txt file.
public ArrayList<Position> readPositions(){
ArrayList<Position> positions = new ArrayList<>();
...
/* for each line in the file, a new `Position` is being created
and being added to `positions` after necessary file operations performed. */
...
// Initializing a new position and adding it to the list
Position position = new Position(...);
positions.add(position);
return positions;
}
}
Position class:
public class Position {
private String stockCode;
private double balance;
...
// There are more than two fields. Truncated it for the sake of the question.
public Position(String stockCode, double balance, ...) {
this.stockCode = stockCode;
this.balance = balance;
...
}
}
And the class in question; Portfolio class:
public class Portfolio {
private ArrayList<Position> positions;
...
private final DataService dataService;
private final ReaderService readerService;
public Portfolio(DataService dataService, ReaderService readerService){
this.dataService = dataService;
this.readerService = readerService;
}
public ArrayList<Position> getPositions() {
return positions;
}
// Check out this method. Is it a poor design?
public void setPositions() {
try {
this.positions = readerService.readPositions();
}
catch (IOException ex){
ex.printStackTrace();
}
}
}
Is it correct thing to question the following:
"A ReaderService is responsible to read the positions, but you are giving it the responsibility of creating list of positions for Portfolio class as well.'
I mean do I break the Single Responsibility principle here?
I am also considering to make these service classes static.
For the sake of readability, I answer here.
Rather than setPositions(), I would like to create with constructor. And create another class (or you can put it in main class as you said, but you may don't like it) as below.
public class PortfolioService {
private final DataService dataService;
private final ReaderService readerService;
public PortfolioService(DataService dataService, ReaderService readerService) {
this.dataService = dataService;
this.readerService = readerService;
}
public PortfolioService createPortfolio() {
return new Portfolio(readerService.readPositions());
}
}
then, Portfolio class will look like this.
public class Portfolio {
private final List<Position> positions;
public Portfolio(List<Position> positions) {
this.positions = positions;
}
// and do something else with positions
}

Append every class field with a constant string in Java

I have lots of classes representing user screens in the application that I am testing (page objects). Each of the page objects contains various number of elements with wach of the having an ID. I need to declare those IDs. It looks something like this:
public class MessagesScreen extends BasePage {
private static final String backArrowButtonID = PACKAGE_NAME_ID + "backArrow";
private static final String noMessagesImageID = PACKAGE_NAME_ID + "empty_messages_icon";
private static final String noMessagesTextViewI = PACKAGE_NAME_ID + "label_no_documents";
private static final String errorTextViewID = PACKAGE_NAME_ID + "text_error_response";
private static final String progressBarID = PACKAGE_NAME_ID + "message_list_progress_bar";
private static final String messagesRecyclerViewID = PACKAGE_NAME_ID + "messageList";
private static final String swipeRefreshLayoutID = PACKAGE_NAME_ID + "swipeRefreshLayout";
private static final String instantMessageLayoutID = PACKAGE_NAME_ID + "item_instant_message_layout";
}
Each of the IDs needs to have the an environmental variable added as above.
My question is: is there any nifty way of not having to repeat this PACKAGE_NAME_ID all the time? Is there a way of automatic assigning the constant string to every new class field?
Using an enum here will improve your code in many ways. In addition to solving your current problem, you'd be using the right tool for constants.
enum IdKey {
BACK_ARROW_BUTTON_ID("backArrow"),
NO_MESSAGES_IMAGE_ID("empty_messages_icon"),
NO_MESSAGES_TEXT_VIEW_ID("label_no_documents"),
ERROR_TEXT_VIEW_ID("text_error_response"),
PROGRESS_BAR_ID("message_list_progress_bar"),
MESSAGES_RECYCLER_VIEW_ID("messageList"),
SWIPE_REFRESH_LAYOUT_ID("swipeRefreshLayout"),
INSTANT_MESSAGE_LAYOUT_ID("item_instant_message_layout");
private final String suffix;
private IdKey(String suffix) {
this.suffix = suffix;
}
public String getSuffix() {
return BasePage.PACKAGE_NAME_ID + this.suffix;
}
}
And all you'd have to do wherever you were using your fields is just call:
IdKey.BACK_ARROW_BUTTON_ID.getSuffix();
And the code is both more reliable and cleaner. You can even nest the enum as a private member of MessagesScreen.
I might consider an enum in this case, you can still reference a specific value in the code and override the toString to return your message in the format you want
I have lots of classes representing user screens in the application that I am testing (page objects). Each of the page objects contains various number of elements with wach of the having an ID. I need to declare those IDs. It looks something like this:
public enum MessagesScreen {
BACK_ARROW("backArrow"),
NO_MESSAGES_IMAGE("empty_messages");
private String value;
private Messages(String value) {
this.value = value;
}
#Override public String toString() {
return PACKAGE_NAME_ID + this.value;
}
}
As you cannot enrich the state of final variables after their valuing, I would do things in the other way : providing a getter that adds the desired prefix.
public class MessagesScreen extends BasePage {
private static final String backArrowButtonID = "backArrow";
private static final String noMessagesImageID = "empty_messages_icon";
///...
public String getIdWithPrefix(String constantValue){
return PACKAGE_NAME_ID + constantValue;
}
}
Note that with an enum it would be more robust as Strings accept a very large range of possible values whereas enums don't.
It will require you to change many classes but it is worthful.
The ernest_k answer shows that very well.

How do i add together values from all objects of a class in java?

I am trying to retrieve certain values from multiple objects under the same class. I have used a for each loop to iterate through each object, and would like to create an aggregated total, representing the rating and the cost of the item from the objects.
The For Each loop in my parent class:
for (Song songObj : Song.returnSongs()) {
totalSongCost += Double.parseDouble(songObj.getPrice());
totalSongRating += Integer.parseInt(songObj.getRating());
}
The Child class ArrayList meant to store objects:
private int rating;
private String title;
private double price;
private boolean favorite;
private static int counter = 0;
private static ArrayList songArray = new ArrayList();
/**
* Constructor for objects of class Song
*/
public Song()
{
// initialise instance variables
rating = 0;
title = "";
price = 0.0;
counter++;
songArray.add(this);
}
public static ArrayList returnSongs() {
return songArray;
}
When I compile the code I get an error message saying that an object cannot be converted to song. Is there a way to fix this, or an easier way to accomplish the same task?
If you've ever read the docs, you will know that ArrayList is actually a generic class. That means you can give ArrayList a type.
The type of stuff that an array list can store depends on what type you gave it. But if you don't give it any type, it stores Objects! Here,
for (Song songObj : Song.returnSongs()) {
you want to get Song objects from an array list of Object objects, which makes no sense to the compiler. As a result, the error appears.
The solution to this problem is of course, give the array list a type so that it knows what type it should store.
Change this
private static ArrayList songArray = new ArrayList();
to this:
private static ArrayList<Song> songArray = new ArrayList<>();
and change this:
public static ArrayList returnSongs() {
to this:
public static ArrayList<Song> returnSongs() {
ArrayList is a generic class. This means you can specify what class type it is meant to work with. if you change this:
private static ArrayList songArray = new ArrayList();
to this:
private static ArrayList<Song> songArray = new ArrayList<Song>();
Then the ArrayList class will understand that you're working with instances of Song.
Edit: as Jim Garrison pointed out, your returnSongs() method should also be changed to specify the class type in the same way.
public static ArrayList<Song> returnSongs() { ...
It's a little unusual to have the Song class be responsible for keeping track of all of the songs within the application. That seems outside of the responsibility of that class, and perhaps better suited to be handled within a different class, either within your parent class or a new type specially defined.
Additionally, be careful when using types like List and ArrayList. As your compiler will warn you, these require type parameters in angle brackets (i.e. List<Type>). You should make it a habit of addressing all compiler warnings, and of always specifying type parameters for generic types like List. In cases where you don't define your types correctly, things start to default to Object, which leads to the issue you faced here.
Below is an example of what this could look like, restructured to keep the Song class solely for attributes of the song itself:
import java.util.ArrayList;
import java.util.List;
public class Parent {
private static List<Song> songs = new ArrayList<Song>();
private static double totalSongCost = 0.0;
private static int totalSongRating = 0;
public static void main(String[] args) {
populateSongs();
for (Song song : songs) {
totalSongCost += songObj.getPrice();
totalSongRating += songObj.getRating();
}
}
private void populateSongs() {
songs.add(new Song(5, "Hey Jude", 12.5));
songs.add(new Song(4, "Angie", 11.5));
songs.add(new Song(0, "Other", 10.5));
}
}
Your song class would simply be this:
public class Song {
private int rating = 0;
private String title = "";
private double price = 0.0;
public Song(int rating, String title, double price) {
this.rating = rating;
this.title = title;
this.price = price;
}
// Compressed for brevity
public int getRating() { return rating; }
public String getTitle() { return title; }
public double getPrice() { return price; }
}

Remove key and value from object

My data model is as follow:
public class CustomerObject implements Serializable
{
public Integer pkid;
public String code;
public String name;
public CustomerObject()
{
pkid = new Integer(0);
code = "";
name = "";
}
}
Now I am calling this from another class:
public CustomerObject getCustObj() {
CustomerObject custObj = new CustomerObject();
custObj.pkid = new Integer(1001);
custObj.code = "CUST1001";
return custObj;
}
Now here in getCustObj() function I want to pass only pkid and code. I mean I want to remove the variable "name" from the object and then pass. So my passing object will look like:
CustomerObject()
{
pkid = 1000;
code = CUST1001;
}
Please help how I can do this.
Actually I have a data model of 200 variable. I will pass this using webservice. But during pass by webservice I may need only 20 to pass. So I want to reduce the data size.
Use another constructor in class CustomerObject as following.
public class CustomerObject implements Serializable
{
public Integer pkid;
public String code;
public String name;
public CustomerObject()
{
pkid = new Integer(0);
code = "";
name = "";
}
public CustomerObject(int inPkid, String inCode)
{
this.pkid = inPkid;
code = inCode;
}
}
When you call getCustomerObject method from another class use as follows
public CustomerObject getCustObj() {
CustomerObject custObj = new CustomerObject(new Integer(1001),"CUST1001");
}
If you are not setting name in your object, then it is as good as object not having name because name is null. You can't remove name variable from the object.
But if you really want to do so, you can use inheritance. Make one class with all attributes except name and other class extends the first class and adds name attribute to it. So now you can use first class when you don't need the name attribute.

Categories