Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I implemented a class Database Manager that manages operations on two database engines. The class has a private variable databaseEngine which is set before using class methods (drop database, create database, run script, compare, disconnect, etc.) and based on this variable the class recognizes how to behave.
However, and I know it's wrong, Database Manager's methods are full of switch cases like this one:
public void CreateNewDatabase(String databaseName){
switch (databaseEngine){
case "mysql":
//Executes a prepared statement for dropping mysql database (databaseName
break;
case "postgres":
//Executes a prepared statement for dropping postgres database (databaseName
break;
...
}
}
I require a good advice about this. I want to load everything from configuration and resources folders, I mean, the prepared statement for creating and dropping, etc. If a new database engine needs to be supported, it won't be a headache as It would just require to save sql sripts in a resources file and any other data in a configuration file. Please, suggest me any design pattern useful for this case.
Whenever you need to invoke different operations based on a switch statement, think about using an abstract class which defines the operation interface and implementation classes which implement the operation.
In your case databaseEngine is a String which names a database. Instead create an abstract class DatabaseEngine and define operations like createDatabase:
public abstract class DatabaseEngine {
public abstract void createDatabase(String databaseName);
public abstract void dropDatabase(String databaseName);
}
and add implementations:
public class PostgresEngine extends DatabaseEngine {
public void createDatabase(String databaseName) {
... // do it the postgres way
}
}
and then use it in your manager class
public void createNewDatabase(String databaseName) {
engine_.createDatabase(databaseName);
}
First thing: switching on strings is so old school; if at all; you would want to use a true enum for that. But of course, that isn't really the point; and switching over enums is as bad as switching over strings (regarding the thing that you have in mind) from a "OO design" point of view.
The solution by wero is definitely the "correct choice" from an OO perspective. You see, good OO design starts with SOLID; and SOLID starts with SRP.
In this case, I would point out the "there is only one reason to change" aspect of SRP. Thing is: if you push all database handling for 2, 3, n different databases into one class ... that means that you have to change that one class if any of your databases requires a change. Besides the obvious: providing "access means" to ONE database is (almost more) than enough of a "single responsibility" for a single class.
Another point of view: this is about balancing. Either you are interested in a good, well structured, "really OO type of" design ... then you have to bite the bullet and either define an interface or abstract base class; that is then implemented/extended differently for each concrete database.
Or you prefer "stuffing everything into one class" ... then just keep what you have, because it really doesn't matter if you use door handles made out of gold or steel ... for a house that was built on a bad basement anyway.
Meaning: your switch statements are just the result of a less-than-optimal design. Now decide if you want to cure the symptom or the root cause of the problem.
I implemented a class Database Manager that manages operations on two database engines.
What if you had three or four or five different databases/storages? For example, Oracle, MongoDB, Redis, etc. Would you still put implementation for all of them into Database Manager?
Database Manager's methods are full of switch cases...
As expected, because you put everything into one class.
Please, suggest me any design pattern useful for this case.
The most straitforward way to simplify your solution would be to separate MySQL and Postgree implementations from each other. You would need to use Factory and Strategy design patterns. If one sees a switch, one should consider using them, but don't be obsessed with patterns. They are NOT your goal, i.e. don't put them everywhere in your code just because you can.
So, you should start from defining your abstractions. Create an interface or an abstract class if there's a functionality common to all database subclasses.
// I'm not sure what methods you need, so I just added methods you mentioned.
public interface MyDatabase {
void drop();
void create();
void runScript();
void compare();
void disconnect();
}
Then you need to implement your databases which in fact are strategies.
public final class MySqlDatabase implements MyDatabase {
#Override
public void drop() {}
...
}
public final class PostgreDatabase implements MyDatabase {
#Override
public void drop() {}
...
}
Finally you need to create a factory. You can make it static or implement an interface if you like.
public class MyDatabaseFactory {
public MyDatabase create(String type) {
switch (type) {
case "mysql":
return new MySqlDatabase();
case "postgress":
return new PostgreDatabase();
default:
throw new IllegalArgumentException();
}
}
}
You don't necessarily have to pass a string. It can be an option/settings class, but they have a tendency to grow which may lead to bloated classes. But don't worry too much about it, it's not your biggest problem at the moment.
Last, but not least. If you don't mind, revise your naming conventions. Please, don't name your classes as managers or helpers.
You could create an abstract base class for your DatabaseEngines like this:
public abstract class DatabaseEngine {
public abstract void createDatabase(final String databaseName);
public abstract void dropDatabase(final String databaseName);
}
And then create concrete implementations for each DatabaseEngine you are supporting:
public final class MySQLEngine extends DatabaseEngine {
#Override
public void createDatabase(final String databaseName) {
}
#Override
public void dropDatabase(final String databaseName) {
}
}
Then when you want to make a call to create/drop it will look more like this:
databaseEngine.createDatabase("whatever");
This is opinion based question: but in my point of view you can use:
Factory Design pattern. This will take care of any other
database added or changed in future.
Example:
public interface IDataBaseEngine {
...
}
public class OracleDBConnection implements IDataBaseEngine {
...
}
public class MySQLDBConnection implements IDataBaseEngine {
....
}
public class DatabaseEngineFactory {
public IDataBaseEngine getDatabaseConnection() {
....
}
}
Second, create files let say xml files which will contains your SQL
and according to your DB (which can be configured) these files will
be converted to its SQL
Example:
SQL file: customer.table
<TABLE>
<SELECT>
<FROM>customer</FROM>
<WHERE>customer_id = ?</WHERE>
<ORDER_BY>customer_id<ORDER_BY>
</SELECT>
</TABLE>
Now if your configuration file says your database is oracle, then while compiling above SQL file it will create following SQL file:
SELECT * FROM customer
WHERE customer_id = ?
ORDER BY customer_id
Related
I am working on a program that supports 3 different platforms. These platforms have identical logic, but the program would have to work with a different database for each one.
I have three different Database.java files for each platform. For example
com.myproject.dao.bmw.Database.java
com.myproject.dao.ford.Database.java
com.myproject.dao.chevy.Database.java
The Database classes all have the same method signatures. But their database connection or queries may be different.
I set the platform name, which in this case is the car make using a config.properties file. I call the methods inside the Database class depending on which platform is set in the config.properties file throughout the program many times.
I want to have to get the Database object based in what is set on the config.properties file when the program starts, while having the same object name for the database. That way each time I call the method names I would not have to use if statements or switches each time I want to use a method in the Database class.
What is the best way to achieve my goal?.
This sounds like a job for the Factory pattern.
Create an interface CarDB (or ICarDb if you like the naming convention like that so you know it is an interface) that contains all the common methods
Create 3 classes that implement CarDB - Ford, Bmw and Chevy
Create a CarDbFactory that has a method like CarDB getDb(Params params) that given your parameters will return a CarDB - the actual one (Ford, Bmw...) depends on the paremeters.
First of all, you did not mention any reasons why you are not considering any of the existing ORM frameworks like Hibernate which is meant specifically for this job. In a nutshell, the ORM allows you to switch across the different databases easily. But if you have a strong reason for not to use the ORM framework, then you can consider the below approach.
Basically, need to define and use the DataBaseConfigFactory and set the appropriate DBConfiguration during the start up of your application as shown below:
DataBaseConfigFactory interface:
public interface DataBaseConfigFactory {
Connection getConnection();
void executeQuery();
}
MyProjectDataBaseConfigFactory class:
public class MyProjectDataBaseConfigFactory implements DataBaseConfigFactory {
private static final DBConfiguration dbConfiguration;
static {
// Get the active db name from props file
// Set dbConfiguration to BmwDBConfiguration or FordDBConfiguration, etc...
}
public Connection getConnection() {
return dbConfiguration.getConnection();
}
public void executeQuery() {
return dbConfiguration.executeQuery();
}
}
Now define a DBConfiguration interface and all specific implementations for the operations that your bmw, ford, etc.. support
DBConfiguration class:
public interface DBConfiguration {
//Add all methods that can be supported by DBConfiguration
}
public class BmwDBConfiguration implements DBConfiguration {
// BMW specific implementations for DBConfiguration
}
public class FordDBConfiguration implements DBConfiguration{
// Ford specific implementations for DBConfiguration
}
In short, you will be using DataBaseConfigFactory interface through out your application to connect with databases and if a new database is added then you need to set the DBConfiguration appropriately.
I try to understand the SOLID principles and therefore implemented some java snippets. My concern is the OCP at the moment. Having following samples,
public abstract class Bakery
{
public abstract Bakegood bake();
}
/******************************************/
public class BreadBakery extends Bakery {
#Override
public Bakegood bake() {
return new Bread();
}
}
/******************************************/
public class CakeBakery extends Bakery {
#Override
public Bakegood bake() {
return new Cake();
}
}
/******************************************/
how can I create the right bakery. Assume a customer comes to the bakery and says: "I'd have two cakes, please!", how can I then instantiate the CakeBakery. Of course I can create an abstract factory like:
public static Bakery createBakery(final String orderedBakegood)
{
switch(bakegood)
{
case "Cake": return new CakeBakery();
case "Bread": return new BreadBakery();
default: throw new InvalidBakeryException();
}
}
But I don't want to use switch or if statements. Is there any other possibility or am I completely wrong with the understanding?
Open/closed principle says:
Software entities (classes, modules, functions, etc.) should be open
for extension, but closed for modification.
So whenever you introduce a new Bakery, you should not modify existing code. You can use something like a registry for your Bakery classes. If you need to add a new Bakery, just extend Bakery class and register it (e.g. at startup). Hence no "if" or "switch" modification is required. Moreover, adding a new Bakery does not require changing the internals of the registry or the code that is calling the registry.
Furthermore, this technique is not dependent on the way you register your components. You can do it programatically, with a configuration file (xml, ...), via classpath scanning, ...
You can see this approach in the Spring framework a lot. Basically the Spring framework is a great source of many design principles.
Here you can see a very simple registry implementation.
public class BakeryRegistry {
private Map<String, Bakery> mapping = new HashMap<>();
public BakeryRegistry() {
loadDefaultMappingFromConfigFile();
}
public Bakery getBakery(String name) {
return mapping.get(name);
}
public void registerBakery(String name, Bakery bakery) {
mapping.put(name, bakery);
}
private void loadDefaultMappingFromConfigFile() {
...
}
}
Maybe article Killing Switch Statements With A Registry can help. It is based on JavaScript but the principle is the same.
The contrived abstraction is causing the problem here. Customers will not ask the bakery for abstract "baked goods", because all baked goods are not substitutable. Bread is not a substitute for cake, and vice versa. Wrapping these two different products into one inheritance hierarchy is a violation of the Liskov Substitution Principle.
The SOLID principles are interrelated, so applying OCP will be difficult or impossible without applying LSP first. See the introduction to LSP where Robert Martin describes inheritance as being critical to OCP, and goes on to describe LSP as being critical to inheritance.
For a small new project, I decided to give JDBI a try (normally I work with hibernate/jpa).
I like the lightweight, annotation based dao creation using #SqlUpdate/#SqlQuery.
But: There are situations where I can't be sure if I want to create an entity or update an existing one.
I would place a "select" statement and depending on its return value use the insert or update statement.
Question: is this somehow supported by the "interface-only" dao in jdbi? Or do I have to write a "createOrUpdate" method myself (making the auto generated dao more or less obsolete)?
Thanks for any hints.
Thanks to #zloster I now built a solution based on an abstract class instead of an interface. Works as required.
#SqlUpdate("insert ...")
public abstract void insert(...);
#SqlUpdate("update...")
public abstract void update();
public X createOrUpdate(final X x) {
if (!exists(x)) {
insert(x);
} else {
update(x);
}
return find(...);
}
I have some Android projects and most of them are connected with SQLite databases. I'm interested is it a good programming practice (or a bad habbit) to use some static class like "DatabaseHelper.class" in which I would have all static method related for database manipulation. For example
public static int getId(Context context, String name) {
dbInit(context);
Cursor result = db.rawQuery("SELECT some_id FROM table WHERE some_name = '" + name + "'", null);
result.moveToFirst();
int id = result.getInt(result.getColumnIndex("some_id"));
result.close();
return id;
}
where dbInit(context) (which is used in all my static methods for database manipluation) is
private static void dbInit(Context context) {
if (db == null) {
db = context.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
}
}
Then when I need something I can easily call those method(s) with for example
int id = DatabaseHelper.getId(this, "Abc");
EDIT: Do I have to use dbClose on every connection or leave it open per-activity and close per-activity? So do I have change that upper code to something like this?
...
dbClose();
return id;
}
private static void dbClose() {
if (db != null) {
db.close();
}
}
I would suggest you get into the habit of getting a database connection every time you need one, and releasing it back when you are done with it. The usual name for such a facility is a "database connection pool".
This moves the connection logic out of your actual code and into the pool, and allow you to do many things later when you need them. One simple thing, could be that the pool logs how long time a connection object was used, so you can get information about the usage of the database.
Your initial pool can be very simple if you only need a single connection.
I would definitely have your database related code in a separate class, but would really recommend against using a static class or Singleton. It might look good at first because of the convenience, but unfortunately it tightly couples your classes, hides their dependencies, and also makes unit testing harder.
The drawbacks section in wikipedia gives you a small overview of why you might want to explore other techniques. You can also head over here or over there where they give concrete examples of a class that uses a database access singleton, and how using dependency injection instead can solve some of the issues I mentioned.
As a first step, I would recommend using a normal class that you instantiate in your constructor, for ex:
public class MyActivity extends Activity {
private DBAccess dbAccess;
public MyActivity() {
dbAccess = new DBAccess(this);
}
}
As a second step, you might want to investigate frameworks like RoboGuice to break the hard dependency. You code would look something like:
public class MyActivity extends Activity {
#Inject private DBAccess dbAccess;
public MyActivity() {
}
}
Let us know if you want more details!
If you're going to use a singleton the very minimum requirement is that you make it stateless/threadsafe. If you use your getId method as it stands concurrent invocations could potentially cause all manner of strange bugs...
dbInit(context);
May be called for Thread A which then stops processing before hitting the query statement. Subsequently Thread B executes getId and also calls dbInit passing in a different context all together. Thread A would then resume and attempt to execute the query on B's context.
Maybe this isn't a problem in your application but I'd recommend sticking a synchronized modifier on that getId method!
I better explain the question with an example.
I have an Interface Model which can be used to access data.
There can be different implementations of Model which can represent the data in various format say XMl , txt format etc. Model is not concerned with the formats.
Lets say one such implementation is myxmlModel.
Now i want to force myxmlModel and every other implementation of Model to follow Singleton Pattern.The usual way is to make myxmlModels constructor private and provide a static factory method to return an instance of myModel class.But the problem is interface cannot have static method definitions and a result i cannot enforce a particular Factory method definition on all implementation of Model. So one implementation may end with providing getObject() and other may have getNewModel()..
One work around is to allow package access to myxmlModel's constructor and create a Factory class which creates the myxmlModel object and cache it for further use.
I was wondering if there is a better way to achieve the same functionality .
Make a factory that returns
instances of your interface, Model.
Make all concrete implementations of the model package-private classes
in the same package as your factory.
If your model is to be a singleton, and you are using java
5+, use enum instead of traditional
singleton, as it is safer.
public enum MyXMLModel{
INSTANCE();
//rest of class
};
EDIT:
Another possibility is to create delegate classes that do all the work and then use an enum to provide all of the Model Options.
for instance:
class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}
class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}
public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());
private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }
public void foo() { delegate.foo(); }
}
You can use reflection. Something like this:
public interface Model {
class Singleton {
public static Model instance(Class<? extends Model> modelClass) {
try {
return (Model)modelClass.getField("instance").get(null);
} catch (blah-blah) {
blah-blah
}
}
}
public class XmlModel implements Model {
private static final Model instance = new XmlModel();
private XmlModel() {
}
}
usage:
Model.Singleton.instance(XmlModel.class)
Actually, I don't like this code much :). First, it uses reflection - very slow, second - there are possibilities of runtime errors in case of wrong definitions of classes.
Can you refactor the interface to be an abstract class? This will allow you to force a particular factory method down to all implementing classes.
I used to ask myself the same question. And I proposed the same answer ;-)
Now I normally drop the "forcing" behavior, I rely on documentation.
I found no case where the Singleton aspect was so compelling that it needed to be enforced by all means.
It is just a "best-practice" for the project.
I usually use Spring to instanciate such an object,
and it is the Spring configuration that makes it a Singleton.
Safe, and so easy ... plus additionnal Spring advantages (such as Proxying, substituing a different object once to make some tests etc...)
This is more an answer to your comment/clarification to kts's answer. Is it so, that the real problem is not using the Singleton pattern but instead defining an eclipse (equinox) extension point schema that allows contributing a singleton?
I think, this can't be done, because everytime you call IConfigurationElement.createExecutableExtension you create a new instance. This is quite incompatible with your singleton requirement. And therefore you need the public default constructor so that everybody can create instances.
Unless you can change the extension point definition so that plugins contribute a ModelFactory rather than a model, like
public interface ModelFactory {
public Model getModelInstance();
}
So the extension user will instantiate a ModelFactory and use it to obtain the singleton.
If I guessed wrong, leave a comment and I delete the answer ;)