As I read, singletons are bad and one should avoid using them.
But I develop an App where most Activities and Fragments need to have access to the same dataset. The datas are stored in a an ArrayList and accessible through a singleton class.
What is bad about that? I can't create a new data-class object for each activity because the ArrayLists will be different. What is the alternative?
singletons are bad and one should avoid using them
In Android app development, we use singletons much more than in traditional Java development.
IMHO, the keys are:
Use them carefully, making sure that you do not introduce memory leaks, race conditions, etc.
Use them for specific roles, such as following the repository pattern, rather than just slapping static on everything because you want to make the compiler stop saying mean things to you
Use them reactively (LiveData, RxJava, Kotlin coroutines, etc.), assuming that the data managed by the singleton is coming from something involving I/O (network, database, file, etc.)
What is bad about that?
Possibly nothing. There may be issues with your specific implementation, but we have few details about that.
Singletons aren't bad per se, the problem with them is when you start trying to test your code.
When you have a class/module/component/view that depends on one or more singletons, you have no way to control that dependency, so in a test environment you cant "mock" that singleton dependency or control whats data is in them (you can, but is really annoying having to clean all singletons before each tests, and even though that is error prone).
This can be easily solved using dependency injection. In Android the best framework for that is Dagger: https://google.github.io/dagger/
You can always use dependency injection by hand too, but having a framework that does the hard work for you is nice.
Then, with this approach, you kinda keep having singletons, but they are not really singletons in the way that they are in charge of only creating a single instance, but you (or the framework) are. Those classes are created only once (at the beginning or lazily) and then are injected in the components/clases that depends on them.
This way, you keep having all its features (sharing data between activities, fragments, etc), but, as you are injecting them, you can mock them an inject mocks for testing purposes.
Related
I was trying to make a simple application in javafx.
I had 8 views (FXML), so one model for each and same for the controllers.
I had to keep the "context" for each model wherever I was... So I had a function setContext which would take a parameter which is a class that regroup every models.
So in every controllers, I had every models.
But a bit latter, I had to had another page, which would take the result of all those page (questionnaire) and show it, so I could have multiple questionnaire... So I was facing the exact same problem, but I didn't want to do it all over again... Because as soon as I'm creating a new questionnaire, I lose the context of the previous one. I also had to add abstractModel and abstractController for stocking every models. It was ratchet.
So I gave up the idea of one controller for each view.
I ended up with a functionnal application, but with one controller which as over 1000 lines... it's only a questionnaire.
I was wondering if there were any possibilities to do what I attempt to do, with multiple controller, but where I don't need to set the "context"? Like... the pages/views auto-save somehow and won't re-instantiate if I'm not asking for it (like a new questionnaire would reset).
Sush as a static class, like a singleton, but for views and which I'm able to instantiate for every questionnaire. But then again, I keep a track on the old ones.
I'm pretty sure it's possible, but can't find anything about it maybe my formulation of the question is just wrong.
Any ideas? Thanks
Your question is bit abstract and it is hard to give a definitive answer. But you might benefit from introducing a dependency injection framework.
One way to do that would be to use Gluon Ignite: "With this library, developers can use popular dependency injection frameworks in their JavaFX applications, including inside their FXML controllers.". You can choose a dependency injection framework you wish from those supported (for example, Dagger, Guice or Spring). With those systems, you can apply scoping rules to your model classes such as Singleton, for those models for which you only wish to have a single instance for your application. You can also use other scoping rules and producers to create models that have different scopes such as within the context of a wizard or created new every time a form is shown, etc.
Beware that using dependency injection frameworks might make your application a little bit more difficult to understand. Anybody maintaining your application has to additionally learn the dependency injection framework. The framework will create objects and inject references to them into your code automatically and your application might be a bit more difficult to debug due to some seemingly magical generated operations that you don't control. Still, it's a tradeoff and, for medium sized applications, the gain in using dependency injection is probably worth it for a lot of apps. From the description you provided, your application may fall into this class, so you should probably seriously consider this approach.
Note that an alternate to a dependency injection system is a service locator (read about it in the Martin Fowler article on dependency injection that I linked earlier). A sample (extremely basic) version of a service locator would be the vista navigator in this small JavaFX navigation framework, though that doesn't pretend to be a full MVC system.
It's just that I can generate multiple questionnaires, which all have the same models and same views and same controllers. But when I create one, it instantiate everything, but it keeps track on all of them so I can edit them later
You could replace your in-memory structure for keeping track of stuff for editing with a persistent storage, for example a JPA based DB access layer or a NoSQL based DB access layer. One advantage of this could also be that the state of the application would be saved if the application is shut down, then restarted, so the user could just pick up where they left off in their questionnaire.
I have been working on a few web applications and REST web services recently (Spring IoC/MVC/Data JPA etc). They usually follow the same pattern: Controller classes --> Service classes (which have several "utility"/business logic classes autowired) --> Spring Data Repositories.
Pretty much all of the classes above are Spring singletons. I feel like this makes the code and some functions within a class dirtier; for example, I can't have a state in a class, I need to pass a lot parameters between methods, and I don't really like having more than 1-2 parameters (although I know sometimes it is necessary).
I was wondering how this problem is overcome in the big (e.g. enterprise) kind of application.
Is it a common practice to use non-Spring managed classes in the Spring application? If so, how do you pass dependencies into it (the ones that would normally be autowired)? If I use constructor injection for example, then I need to autowire all necessary dependencies into the class that creates the object and I wanted to avoid that. Also, I don't really want to be messing with load time weaving etc. to autowire beans into non-Spring objects.
Is using prototype scoped beans a good solution? The only thing is that I need to use AOP's scoped proxies (or method injection etc) to make sure that I get a new instance for any bean that is autowired into a singleton in the first place. Is that a "clean" and reliable option (i.e., is it certain that there will be no concurrency type of issues)? Can I still autowire any singletons into those classes with no issues?
Does anyone that worked on a large system (and actually managed to keep the structure not "bloated" and clean) have any recommendations? Maybe there are some patterns I am not aware and could use?
Any help appreciated.
Spring is well designed, you must not worry about about IoC implementation of DI. The pattern that you have mentioned /Controller Layer -> Service Layer -> Data Access Layer/ is good in practice, and it is ok that these singleton objects does not have state because of rule of OOP: "Think about objects as service providers that does one thing well". Models can have state as JPA units for storing something in Database. Is not mandatory that in large systems you will have dirty code how you mentioned passing a lot of parameters, it just depends on your design decision that will need a deeper construction.
I've read about how to use Spring in standalone applications but I'm not sure what should be the approach for refactoring a large code base of 120,000 lines for making the change as gradual as possible.
As far as I understand Spring won't inject anything in an object unless that object is managed by the application context. If this is true, I think I have two choices:
1- Start refactoring from the main class down, but this means complicated scenarios will appear soon.
2- Share the application context statically so that I can start refactoring the simplest things, scalating in difficulty when I'm ready.
I'm not a fan of static access so I would try to avoid that choice, but I don't know if it's a good idea to start with the huge classes that are loaded at startup. Any ideas of the best approach?
By the way, is it OK to inject Swing components until I can fix the dependencies?
I think that before approaching such a big technology change, it may be a good idea to start asking yourself if you are following the architecture that Spring guides you to have when you start using it from the beginning.
Therefore, is your application based on the MVC pattern?
If not, maybe your product is not yet ready for being refactored to
use Spring. In this case, I would suggest refactoring the product
design first, so that it complies with the MVC architectural pattern.
If yes, then I would proceed with a use-case-based approach, starting
from the use cases that required a complicated design and
implementation.
E.g. I would look for very important entity classes or business classes containing a lot of logic. This way, you can reduce the risk of doing a lot of refactoring before realizing that, for example, Spring is not a good fit for the core of your product.
After identifying the most critical use case, you can start to experiment how refactoring works on your current product by introducing Spring from end to end on a single critical scenario (user input - business logic - entity manipulation - persistence). If you are successful, then you keep refactoring, otherwise you can go back and try to understand where you need to change your current product before introducing Spring.
Of course, this works when you have some experience with Spring and you do not have to cope with newcomer's issues. If you are new to Spring, then I would recommend getting some experience with Spring before starting the adventure of refactoring such a big project.
Start simply and wire new code/class with spring. You'll amend your existing main method to initialise the ApplicationContext and load your new feature. Over time then as change requests arrive you'll refactor and migrate the existing codebase to use spring dependency injection.
I have some Classes like Clipboard or ProcessRegister that I only want to run once in my Project, so only one instance.
My Question in now: How do I distribute those instances best in my Project.
ATM both are singleton and object they use the get an instance over the getInstance().
Another Idea of mine is to create a class Project, that has some static methods like getProjectClipboard()or getProcessRegister()that return the instances.
What is the best way to distribute them? Are there any patterns for that?
Greetings Dennis
There are mainly two patterns that can be used: the service locator, and dependency injection. The service locator pattern is probably the one you are referring to, where everywhere you look for a reference for these objects you explicitly retrieve it from a central location, which for simple java applications is usually a bunch of static methods. this is OK, and I don't think there is an overall better approach here, just make sure that you have only one static method for each singleton, and that you call it always.
Then a few years ago, a shift of mentality became mainstream, dependency injection, and its more popular framework... Spring, with this paradigm, in each place you need to access this singletons, you don't specify where they are, but your object get the correct references injected...
I would recommend you to look into dependency injection... and probably Spring, as it is the mainstream solution for it... I think that giving you more insgight into Spring is out of the scope of the question, but there is A LOT of documentation in Internet if you search for Spring tutorials or something similar...
Basically what you would do is create as spring beans each of your singletons, and then have spring injecting them into your objects... The caveat to this approach is that all of your objects have to be built by Spring, but in practice it doesn't suppose any disadvantage, it will actually make your life easier in terms of testings, maintenance...
Singletons, when done at language level, are global objects. This may work for small projects but is not the best idea when the project grows. There may evolve a situation where suddenly a singleton is only a singleton relative to a certain scope. Then you have to touch the object and every access to it.
That said if you have a Project object or an Application object these are good places to have accessors to Project-relative singletons. If Project is just a class that provides a lot of static accessors it is like a namespace. It is a win in clarity and will make refactoring easier but it doesn't change much in terms of architecture.
Best way to do singletons is not on language level but on application level. Very helpful are application and dependency frameworks like Spring (where the standard scope for beans is in fact singleton). If you later on see that the object isn't singleton you just change the configuration - but not the object itself.
As someone who is usually against the usage of stateful singletons (except for caching purposes), I would say: have one instance of these classes per running application and inject them where you need them (see Dependency Injection). That will also allow you to run the same application multiple times with different configuration in the same JVM.
I am currently working on some older java code that was developed without App Servers in mind. It is basically a bunch of "black box code" with an input interface, and an output interface. Everything in the "black box" classes are static Data Structures that contain state, which are put through algorithms at timed intervals (every 10 seconds). The black box is started from a main method.
To keep this easy for myself, I am thinking of making the "black box" a Singleton. Basically, anyone who wants to access the logic inside of the black box will get the same instance. This will allow me to use Message Driven beans as input to the black box, and a JMS Publisher of some sort as the output of the black box.
How bad of an idea is this? Any tips?
One of the main concerns I have though, is there may be Threads in the "black box" code that I am unaware of.
Is there such thing as "application scoped objects" in EJB?
Note: I am using Glassfish
If you use a simple singelton, you will be facing problems once you enter a clustered environment.
In such scenario, you have multiple classloaders on multiple JVMs, and your sinlgeton pattern will break as you will have several instances of that class.
The only acceptable use for a singleton in an app server (potentially in a clustered environment) is when you the singleton is totally state-less, and is only used as a convenience to access global data/functions.
I suggest checking your application server vendor's solution for this issue. Most, if not all vendors, supply some solution for requirements of your sort.
Specifically for Glassfish, which you say you are using, check out Singleton EJB support for Glassfish. It might be as simple as adding a single annotation.
I would say that creating a singleton is actually the only viable idea. Assuming that code inside this "black box" is known to use static fields, it is absolutely unsafe to create two instances of this facade. Results are unpredictable otherwise.
Far from being a bad idea, it actually sounds to me like potentially quite a good idea.
Just from a program design point of view: if your black box is conceptually an "object" with properties and methods that work on them, then make it into an object, even if there'll only ever be one of them instantiated.
It should work, but there are some issues you may have to deal with.
Threading, as you have mentioned. An MDB is run in the EJB container where you cannot create your own threads, so you have a potential problem there. If you have access to the actual code (which it sounds like you do), you may want to do some refactoring to either eliminate the threads or use an "approved" threading method. The CommonJ TimerManager will probably work in your stated case since it is performing some task on an interval. There are implementations available for most app servers (WAS and Weblogic have it included).
Classloading - This is dependent on you configuration. If the singleton is created and manipulated from MDB's within the same EAR, you will be fine. Separate EAR's will mean different classloaders and multiple instance of you Singleton. Can't comment on whether this would be a problem in your case or not without more information.
I'm missing a point? You mentioned that the 'black box code' contains state. MDBs may be limited to 1 instance per destination but without proper configuration you will end up with a few MDBs. All of them working with your single instance of 'black box code'. For me it seems this is not a good idea, because one bean will override the 'black box code' state a other bean has created a few ticks before.
It seems to me that the artifact that better fits to your requirement is a JBoss MBean. (If you are thinking on JBoss as AS candidate).
Standard MBean Example
MBeans can also be deployed as Singletons, in case of JBoss clustering.
Clustering with JBoss
I hope that this is useful for you.
Rafa.
Fix the code to get rid of the statics as soon as possible. Singletons are not a step in the right direction - they just add extra misdirection.
Don't use Singletons where state may change.
Exposing the global instance of your black-box class doesn't seem like the way to go. Often times, singletons will seem like they will make things easier on you, and in a way they can, but it often comes back to bite you and you end up having to restructure a large chunk of your code.
In the webserver world, an object can be scoped to the request, the session, or the application. Perhaps what you need is a application-scope object.
Search the docs for "application scope object" or "application lifetime object".
Why not create a rest interface for the blank box thingy and let clients make http calls ?
IMO, it's a good idea to have an EJB container of your Singleton needs. In Java EE 6 placing a #Singleton annotation in your session bean gives you a named singleton.