What is the correct way I should initialise my class in android, the class is called Compilation and it has all its values in the db.
I can do the following :
1
public Compilation(int id)
{
// get db singleton here and fill all values
// however I feel this is bad OO because nobody knows I am doing this
}
2
public Compilation(int id, SQLiteDatabase db)
{
// use the provided db to get the info
// however now all calling classes will have to get the db for me
}
3
// get all compilations at once
SQLiteDatabase db = DatabaseHelper.getInstance().getReadableDatabase();
Cursor c = db.rawQuery("SELECT * FROM Compilation", null);
while(c.moveToNext())
{
// get all params here
Compilation comp = new Compilation (a,b,c,d,e);
}
public Compilation(a,b,c,d,e)
{
// just assign all the values given to private vars
}
The problem I see with this is that now the Compilation class is no longer so self contained, it needs another class to initialise it.
Which one is the proper way to do it?
The general rule in software design tells us that we should create Classes which have the minimum dependency on other parts of the software system. This way we end up with Classes which are better reusable.
The first alternative you have proposed is the worst one because its create a very tight dependency on one specific data provider( sqlite ). Maintenance of such class can be a nightmare( Just imagine that the next release of Android will come with sqlite or mysql :) and you want to switch to mysql)
The second one is kinda better if you would replace the constructor parameter from a Class to an Interface and thus creating something that we call Dependency injection .However there are better ways of doing dependency injection on Android (check out for example Dagger)
The third one seems to me as the best fit, since you don't create any dependency. Perhaps to ease the creation of such classes (and to make the code a little bit more "enterprise"), you could create a factory class which would create the instances of Compilation Class (more about this here )
In the very end however this is not a question about Android best practices but about software design decisions which highly depend on what are you trying to do!
All your options are correct, but I think a factory based approach will work fine. I've used it in different occasions. I just wrote down a skeleton of such an alternative approach.
public class CompilationFactory
{
// DB instance and/or cache implementation (HashMap based or via 3rd party lib)
static
{
// DB init stuff here
// if your app logic allows it you can also cache Compilation to avoid
// reading the DB multiple times
}
public static Compilation compilationForId(int id)
{
// either read your Compilation from the DB or from the precomputed cache
}
}
I wouldn't do it this way, I'd use an empty constructor then use an Application (http://developer.android.com/reference/android/app/Application.html) and serve my self the DB from the Application so I don't have to keep instantiating. Might be too advanced if you're doing a school project but yeah..
This depends slightly on the implementation of your Database - if you're using content providers or not, etc.
All of the provided examples are "correct" from the standpoint that they will work. That said number 3 is a red flag to me. Without further code to clarify you run the risk of calling "getReadableDatabase" more than once, which is unescesary.
Beyond that point, it's difficult to know exactly what to recommend you here. There are fancy ways to do this, and they might be overkill for you depending on your projects nature.
I'm going to operate under the assumption that you have a Class which manages Compilations. Something like, and keepping it simple in this case would be the following:
public class CompliationManager() {
private ArrayList<Compilation> myCompilations = new ArrayList<Compilation>();
SQLiteDatabase db;
public CompilationManager() {
db = DatabaseHelper.getInstance().getReadableDatabase();
}
public void loadCompliations() {
Cursor c = db.rawQuery("SELECT * FROM Compilation", null);
while(c.moveToNext()) {
Compilation comp = new Compilation(c);
myCompilations.add(comp);
}
c.close();
}
}
public class Compilation() {
public Compilation(Cursor c) {
// do the actual retrival, setting of fields etc...
getCompilationFromCursor();
}
}
Related
If we have a Class Book and we want to calculate the score of a Book following some rules like "if the number of pages is lower than X then we need to substract Y from the score" and using an Hexagonal Architecture. Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
1st approach
package com.xxx.domain;
[...]
public class Book {
[...]
public Double score() {
[...]
}
[...]
}
2nd approach
package com.xxx.application;
[...]
public interface ScoreService {
[...]
void calculateScore(Book book);
[...]
}
Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
First the clean architecture is very clear when it comes to the question "Where should business logic be placed?".
Application agnostic business logic in the entities layer.
Application specific business logic in the use case layer.
But I think your question is about something a bit different, it's about anemic or rich domain models. I can't tell you every of my thoughts here, but I have written down most of them in the blog I linked in the sentence before.
The condensed statement of mine is
rich domain models combine data and logic while anemic models separate them.
Let's think about the anemic way...
If you place the logic in a separate service it usually means that you have to expose all properties of the book. You will make them public or at least package scope if the service is in the same package.
Your question also focuses on change. You make the statement that logic changes can be better handled if the logic is put in a separate service. That's true, but it comes at a cost.
It's true that an anemic model let you add logic easier, but it is also true that each logic (each service) must have the same interpretation of the anemic model. I mean each service must know how to modify the data structure properly to keep it consistent and that will be hard to maintain when the number of services grows.
But implementing the service can also be a good intermediate step, because it will give you a hint about cohesion. The cohesion usually shows you where to place a method. E.g.
public class ScoreService {
public BookScore calculateScore(Book book, BookRentals rentals){
int pageCount = book.getPageCount();
Author author = book.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = book.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
When you look at the calculateScore above you will recognize that there are a lot of get invocations on Book and less on BookRentals. This is a hint that most of the data that calculateScore needs is placed in the Book. Thus the calculateScore's cohesion is higher to Book and the method might be placed in the Bookclass. E.g.
public class Book {
public BookScore getScore(BookRentals rentals){
int pageCount = this.getPageCount();
Author author = this.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = this.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
The difference is obvious:
the number of method parameters decreases. Maybe you apply DDD and Book is an aggregation root and also has access to BookRentals. Then your parameters might decrease to zero.
Since most of the properties that getScore needs are located in the Book class, you might want to lower their visibilily to private. So that uncontrolled access is not allowed.
One question that often arises when developers put the logic in the entities is: "How can an entity access data from a data store?"
My solution is to just pass a repository to the methods that need it. E.g.
public class Book {
public BookScore getScore(BookRentalRepository repo){
// ...
int rentalCount = repo.getRentalCountSince(this, someDate);
}
}
Whatever way you want to go, anemic or rich, keep the logic in a POJO. Also keep in mind that a POJO can be more than a simple data structure.
I hope my answer helps you to make a decision for your specific application.
If the calc of the score depends only on the book state, i would create a method in the book entity to calc it.
Otherwise, if it depends on other domain objects also, i would create a domain service for calculating it.
Regarding to persist the score. I would persist it just if the calc process is very complicated and takes a lot of time. Otherwise, I wouldn't persist it and calc it when need it.
In case you persist jt, you have to consider that you have to recalculate it and persist the new value every time the other values it depends on change too.
Trying to understand the concept of encapsulation, I came across this definition "Combining the attributes and methods in the same entity in such a way as to hide what should be hidden and make visible what is intended to be visible".
But practicing the same, I am not sure which of the following code is more apt for OOP:
public class Square {
//private attribute
private int square;
//public interface
public int getSquare(int value) {
this.square = value * value;
return this.square;
}
}
or
public class Square {
//private attribute
private int square;
//public interface
public int getSquare(int value) {
this.square = calculateSquare(value);
return this.square;
}
//private implementation
private int calculateSquare(int value) {
return value * value;
}
}
Combining the attributes and methods in the same entity in such a way as to hide what should be hidden and make visible what is intended to be visible
This is a potentially misleading statement. You are NOT hiding anything from anyone. It is also not about methods or fields. Unfortunately this is the way things are worded in almost every place.
How
When writing any piece of program, (be it a function, class, module, or library) we think of the piece we are working on as my code, every other code as my client code. Now assume that all the client code is written by someone else, NOT you. You write just this code. Just assume this, even if you are the only one person working on the entire project.
Now the client code needs to interact with my code. So my code should be nice and decent to talk to. The concept of encapsulation says, that I partition my code in two parts, (1) that the client code should be bothered with, (2) that the client code should NOT be bothered with. The OO way of achieving encapsulation is by using keywords like public and private. The non OO way of achieving this is naming convention like leading underscores. Remember, you are not hiding, you are just marking it as none-of-your-business.
Why
So why should we encapsulate things? What should be organize my code into public and private regions? When someone uses my code, they are of-course using the whole thing, not just public thing, so how come private is something that is none-of-their-business? Note here words like someone and their could refer to yourself - but only while working on the other piece of code.
The answer is easy testability and maintainability. A complete project if tested exhaustively, can be quite a task. So at minimum, when you are done coding, you just test the public aspects of my code. You do not test any of the client code, you do not test any of the private aspects of my code. This reduces test effort while preserving sufficient coverage.
Another aspect is maintainability. My code will NEVER be perfect, it WILL need revisions. Either because of bugfix or enhancement, my code will need tinkering. So when a new version of my code is available, how much is client code impacted? None, if changes are in private regions. Also, while planning a change, we try to confine it as much as possible in private regions. So the change, from client's perspective becomes a no-impact. A change in public aspects of my code, will almost always require changes in client code, now that will need testing. While planning the big picture of my code, we try to maximize the area under private regions and minimize the area under public regions.
And more
The idea of encapsulating links with the idea of abstracting which in turn links with idea of polymorphism. None of these are strictly about OO. Even in non OO world like C or even Assembly, these apply. The way to achieve these differ. Even this applies to things beyond computers.
The process of sewage management, for example, is
encapsulated within the public interface of drains. The general public bothers only with the drains. The treatment, the disposal, the recycling are none of general public's business. Thus, the sewage management could be treated as an -
abstract entity - an interface with just the drains. Different government and companies implement this in their own way. Now an city may have a permanent system of sewage management, or it can periodically -
switch providers. In fifty years of government operation, the situation was bad, but once they contracted that BigCorp Inc, now people can breathe free. We just did polymorphism. We switched implementations, keeping the public interface same. Both government and the BigCorp Inc use the same drains, but their own processing facilities, which are encapsulated away and polymorphically switchable.
In your code
In both your codes you chose to encapsulate the storage, the field is made private. This is a nice approach and certainly OO way. In both of your codes, the algorithm is also encapsulated - i.e not visible to the client. Nice. In your second code, you went ahead and extracted the algorithm in a separate non-public method. This is commendable approach, although obviously an overkill for doing something trivial. Better OO none the less.
What you did in second code even has a name: the strategy pattern. Even though here it is useless (and overkill), it could be useful in a scenario when let say you are dealing with extremely large numbers, such that calculating their squares take very long time. In such a scenario, you could make your calculateSquare method protected, have a class FastButApproxSquare extends Square, and override the calculateSquare method with a different algo which calculates an approx value much faster. This way you could do Polymorphism. Whoever needs exact value will use the Square class. Whoever needs approx value will use FastButApproxSquare class.
Encapsulation is about hiding implementation and structure details from client code. In addition it is about coherence: keep things close together which are highly related to each other.
For example consider a class which manages players of a football team:
public class FootballTeam {
public final List<Player> players = new ArrayList<>();
}
Client code would have access to the list of players, to look them up, to add players and so on:
public class FootballManager {
private final FootballTeam team = new FootballTeam();
public void hirePlayer(Player player) {
team.players.add(player);
}
public void firePlayer(int jerseyNo) {
Optional<Player> player = team.players.stream()
.filter(p -> p.getJerseyNo() == jerseyNo)
.findFirst();
player.ifPresent(p -> team.players.remove(p));
}
}
Now, if someone decides to change the field FootballTeam.players into a Map<Integer, Player>, mapping the players jersey number to the player, the client code would break.
In addition the client code deals with aspects / features closely related to a player. To protect the client code and to ensure changeability of the FootballTeam implementation hide all implementation details, keep player related functionality close to the structure, representing the team and reduce the public interface surface:
public class FootballTeam {
private final Map<Integer, Player> players = new HashMap<>();
public void addPlayer(Player player) {
players.put(player.getJerseyNo(), player);
}
public Optional<Player> lookupPlayer(int jerseyNo) {
return Optional.ofNullable(players.get(jerseyNo));
}
public void remove(Player player) {
players.remove(player.getJerseyNo());
}
}
public class FootballManager {
private final FootballTeam team = new FootballTeam();
public void hirePlayer(Player player) {
team.addPlayer(player);
}
public void firePlayer(int jerseyNo) {
team.lookupPlayer(jerseyNo)
.ifPresent(player -> team.remove(player));
}
}
If any code serves the purpose of encapsulation then that code is correct. The purpose of encapsulation is to provide a process of hiding the variables from other classes (i.e. by making the variable as private) and also to provide a way for other classes to access and modify the variables. Both of your code serves this purpose correctly.
If you would have used "calculateSquare(int value)" method as "public" then there would have been a problem. Other class could call this method directly without using set/get method. So as far as your this method is "private" I think both the codes are all right.
The problem I am having is quite specific, and a bit difficult to explain. Let me know if you need more details about anything. I have an abstract class called System. To hold my System objects, I have a SystemManager which contains an list of Systems, and some functions for manipulating it. Inside it contains:
List<System> systems = new ArrayList<System>();
Now, I want to create another abstract class which is a specific type of System called RenderSystem. This will inherit from System but have a few more functions. I also want to create a RenderSystemManager which should do everything SystemManager does, except with a few extra features. Also, instead of having a list of System in the manager, I would like it to have a list of RenderSystem to ensure that the programmers don't put any regular System objects in it. My initial instinct was to inherit SystemManger, and just change the type of the list to RenderSystem:
systems = new ArrayList<RenderSystem>();
Java doesn't allow this as systems is type System not RenderSystem. I would have assumed it would be OK considering RenderSystem inherits from System. One way I can think of to resolve this issue is to copy and paste all the code from SystemManager into RenderSystemManager and just change the line of code to be:
List<RenderSystem> systems = new ArrayList<RenderSystem>();
My other instinct would be to override the addSystem(System system) function to ensure that it only handles RenderSystem, but the programmers might think they are allowed to do it even if it doesn't work.
#Override
public void addSystem(System system)
{
if (system instanceof RenderSystem)
{
super.addSystem(system);
}
}
These doesn't seem very elegant though. Anybody have any suggestions?
Your managers have the same type-safety requirements as the list they wrap. They should thus follow the same strategy, and be generic types:
public class BaseSystemManager<T extends System> {
private List<T> systems = new ArrayList<>();
public void addSystem(T system) {
systems.add(system);
}
// common methods
}
public class SystemManager extends BaseSystemManager<System> {
// methods specific to System handling
}
public RenderSystemManager extends BaseSystemManager<RenderSystem> {
// methods specific to RenderSystem handling
}
I think your second instinct to add protection into the addSystem call is the correct one. That way SystemManager can still operate on the list of Systems. However I would change the implementation of addSystem to instruct developers in the proper usage:
#Override
public void addSystem(System system)
{
if (system instanceof RenderSystem)
{
super.addSystem(system);
}
else
{
throw new IllegalArgumentException("Only RenderSystem objects can be added to a RenderSystemManager");
}
}
Your SystemManager could have a a list of System objects, and the list could be private, and the only way to add an object to that list would be a function that only took a RenderSystem as an argument. You're trying to manhandle generics into a use for which they probably are not appropriate.
But I think you have bigger problems.
I think this happens to many of us when we start trying to design "from the inside out", i.e., you are taking programming constructs and trying to string them together at a level of detail that ignores (or forgets) what the code is trying to do from a higher level. It's like saying "I want a while loop inside a do loop that has a switch statement with try-catch-finally-whatever, but I don't want to nest all these damn braces."
Take a few steps back and think about the external functionality you want to accomplish, and progress in small steps through design and implementation details from there...
I have a method that looks like this
public Dao<ModelStore, Integer> getDaoStore() throws SQLException {
return BaseDaoImpl.createDao(getConnectionSource(), ModelStore.class);
}
when i call getDaoStore it is quite a lengthy process. In my log's i can see that the GC runs after every call to this, so I'm guessing there's a lot going on with this call.
Is there a way to speed this up?
A deep examination of Android-land has revealed that because of a gross Method.equals() method, annotations under Android are very slow and extremely GC intensive. We added table configuration files in version 4.26 that bypass this and make ORMLite start much, much faster. See this question and this thread on the mailing list.
We continue to improve annotation speeds. See also: ORMLite poor performance on Android?
DAO creation is a relatively expensive process. ORMLite creates a data representation of both the class and the fields in the class and builds a number of other utility classes that help with the various DAO functionality. You should make sure that you call the createDao method once per invocation. I assume this is under Android #Pzanno?
In 4.16 we added a DaoManager whose job it is to cache the Dao classes and this was improved in version 4.20. You should then always use it to create your Daos. Something like the following code is recommended:
private Dao<ModelStore, Integer> modelStoreDao = null;
...
public Dao<ModelStore, Integer> getDaoStore() throws SQLException {
if (modelStoreDao == null) {
modelStoreDao = DaoManager.createDao(getConnectionSource(),
ModelStore.class);
}
return modelStoreDao;
}
Hope this helps. A memory audit of ORMLite is probably also in order. It's been a while since I looked at it's consumption.
This might sound like a weird idea and I haven't thought it through properly yet.
Say you have an application that ends up requiring a certain number of singletons to do some I/O for example. You could write one singleton and basically reproduce the code as many times as needed.
However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind. What would be a solution to make multiple somethings that could each act as a singleton.
P.S: This is for a project where a framework such as Spring can't be used.
You could introduce an abstraction like this:
public abstract class Singleton<T> {
private T object;
public synchronized T get() {
if (object == null) {
object = create();
}
return object;
}
protected abstract T create();
}
Then for each singleton, you just need to write this:
public final Singleton<Database> database = new Singleton<Database>() {
#Override
protected Database create() {
// connect to the database, return the Database instance
}
};
public final Singleton<LogCluster> logs = new Singleton<LogCluster>() {
...
Then you can use the singletons by writing database.get(). If the singleton hasn't been created, it is created and initialized.
The reason people probably don't do this, and prefer to just repeatedly write something like this:
private Database database;
public synchronized Database getDatabase() {
if (database == null) {
// connect to the database, assign the database field
}
return database;
}
private LogCluster logs;
public synchronized LogCluster getLogs() {
...
Is because in the end it is only one more line of code for each singleton, and the chance of getting the initialize-singleton pattern wrong is pretty low.
However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind.
That is not correct. As programmers, we are supposed to come up with solutions that meet the following criteria:
meet the functional requirements; e.g. perform as required without bugs,
are delivered within the mandated timeframe,
are maintainable; e.g. the next developer can read and modify the code,
performs fast enough for the task in hand, and
can be reused in future tasks.
(These criteria are roughly ordered by decreasing priority, though different contexts may dictate a different order.)
Inventiveness is NOT a requirement, and "avoid[ing] redundancy or repetition of any kind" is not either. In fact both of these can be distinctly harmful ... if the programmer ignores the real criteria.
Bringing this back to your question. You should only be looking for alternative ways to do singletons if it is going to actually make the code more maintainable. Complicated "inventive" solutions may well return to bite you (or the people who have to maintain your code in the future), even if they succeed in reducing the number of lines of repeated code.
And as others have pointed out (e.g. #BalusC), current thinking is that the singleton pattern should be avoided in a lot of classes of application.
There does exist a multiton pattern. Regardless, I am 60% certain that the real solution to the original problem is a RDBMS.
#BalusC is right, but I will say it more strongly, Singletons are evil in all contexts.
Webapps, desktop apps, etc. Just don't do it.
All a singleton is in reality is a global wad of data. Global data is bad. It makes proper unit testing impossible. It makes tracing down weird bugs much, much harder.
The Gang of Four book is flat out wrong here. Or at least obsolete by a decade and a half.
If you want only one instance, have a factory that makes only one. Its easy.
How about passing a parameter to the function that creates the singleton (for example, it's name or specialization), that knows to create a singleton for each unique parameter?
I know you asked about Java, but here is a solution in PHP as an example:
abstract class Singleton
{
protected function __construct()
{
}
final public static function getInstance()
{
static $instances = array();
$calledClass = get_called_class();
if (!isset($instances[$calledClass]))
{
$instances[$calledClass] = new $calledClass();
}
return $instances[$calledClass];
}
final private function __clone()
{
}
}
Then you just write:
class Database extends Singleton {}