Is having to pass Context to most classes a sign of bad design?
Android is designed in such a way that in order for a method to read a resource, it must have a access to a Context.
Since most of the classes in my application rely on the flexibility of string resources (e.g. changing language without having to change code, etc.), my simple solution was to pass a Context in their constructor, to provide resource access to each such class.
It doesn't make sense for me to only pass a string in the constructor, because the class needs the flexibility of access to a varying number of strings.
So, to simplify things, I only pass Context, and whenever a string resource is needed, I just use Context.getString().
Is this a sign of bad design?
Is there a better way to accomplish this?
java android oop
add a comment |
Android is designed in such a way that in order for a method to read a resource, it must have a access to a Context.
Since most of the classes in my application rely on the flexibility of string resources (e.g. changing language without having to change code, etc.), my simple solution was to pass a Context in their constructor, to provide resource access to each such class.
It doesn't make sense for me to only pass a string in the constructor, because the class needs the flexibility of access to a varying number of strings.
So, to simplify things, I only pass Context, and whenever a string resource is needed, I just use Context.getString().
Is this a sign of bad design?
Is there a better way to accomplish this?
java android oop
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
2
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
I disagree, I think the design works for what it was intended to do. TheContext
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.
– Austyn Mahoney
Sep 20 '11 at 21:01
add a comment |
Android is designed in such a way that in order for a method to read a resource, it must have a access to a Context.
Since most of the classes in my application rely on the flexibility of string resources (e.g. changing language without having to change code, etc.), my simple solution was to pass a Context in their constructor, to provide resource access to each such class.
It doesn't make sense for me to only pass a string in the constructor, because the class needs the flexibility of access to a varying number of strings.
So, to simplify things, I only pass Context, and whenever a string resource is needed, I just use Context.getString().
Is this a sign of bad design?
Is there a better way to accomplish this?
java android oop
Android is designed in such a way that in order for a method to read a resource, it must have a access to a Context.
Since most of the classes in my application rely on the flexibility of string resources (e.g. changing language without having to change code, etc.), my simple solution was to pass a Context in their constructor, to provide resource access to each such class.
It doesn't make sense for me to only pass a string in the constructor, because the class needs the flexibility of access to a varying number of strings.
So, to simplify things, I only pass Context, and whenever a string resource is needed, I just use Context.getString().
Is this a sign of bad design?
Is there a better way to accomplish this?
java android oop
java android oop
asked Sep 20 '11 at 19:15
uTubeFanuTubeFan
2,979113364
2,979113364
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
2
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
I disagree, I think the design works for what it was intended to do. TheContext
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.
– Austyn Mahoney
Sep 20 '11 at 21:01
add a comment |
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
2
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
I disagree, I think the design works for what it was intended to do. TheContext
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.
– Austyn Mahoney
Sep 20 '11 at 21:01
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
2
2
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
I disagree, I think the design works for what it was intended to do. The
Context
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.– Austyn Mahoney
Sep 20 '11 at 21:01
I disagree, I think the design works for what it was intended to do. The
Context
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.– Austyn Mahoney
Sep 20 '11 at 21:01
add a comment |
4 Answers
4
active
oldest
votes
This is one of the rare occasions where a globally accessible singleton class may be better than passing the Context
to every single class.
I would consider creating a singleton for localization, then use the Context
inside of there (unless you need other aspects of the Context
all over the place).
Of course, this is a matter of taste and preference. YMMV
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
TheContext
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member inonCreate()
. How are you initializing the member, are you callinggetApplicationContext()
?
– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declarepublic static Context appContext;
. 2nd, in onCreate() initialize it:if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?
– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
|
show 1 more comment
This is the Service locator pattern - you pass around a service locator (often called "Context") and get the required dependencies from it. It is not an anti-pattern, and is not that much of a bad design, but usually dependency injection is considered superior.
What you are doing is - passing the service locator even further down the object graph. What is advisable is to give each class only the dependencies it needs. So instead of passing Context
in the constructor, you pass all the strings it requires. That way you won't be violating the Law of Demeter
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
|
show 8 more comments
Sending regularly contexts as parameters and remember them is dangerous, read here: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Much better is to subclass Application and to make singleton with it (the application object is context too). Such sollution doesn't have significant drawbacks.
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
add a comment |
I don't know if it's a bad practice to use it this way, but I did time comparison that took to load 200 light-weight object into Array-list with one of the Constructors taking Context as parameter, and other one getting the required context through static method like @Eric Farr suggested. End result was that accessing context through static method instead of passing to constructor was always 5-25% faster..
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initBlocks(map); // takes context through static method
blocks.clear();
initBlocks(getContext(), map); // pass context down to every block object
mainthread = new GameThread(getHolder(), this);
mainthread.setRunning(true);
mainthread.start();
}
I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects,
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects,
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects,
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects,
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms
I don't know about you, but I'll take an increase in performance (y).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7490518%2fis-having-to-pass-context-to-most-classes-a-sign-of-bad-design%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is one of the rare occasions where a globally accessible singleton class may be better than passing the Context
to every single class.
I would consider creating a singleton for localization, then use the Context
inside of there (unless you need other aspects of the Context
all over the place).
Of course, this is a matter of taste and preference. YMMV
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
TheContext
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member inonCreate()
. How are you initializing the member, are you callinggetApplicationContext()
?
– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declarepublic static Context appContext;
. 2nd, in onCreate() initialize it:if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?
– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
|
show 1 more comment
This is one of the rare occasions where a globally accessible singleton class may be better than passing the Context
to every single class.
I would consider creating a singleton for localization, then use the Context
inside of there (unless you need other aspects of the Context
all over the place).
Of course, this is a matter of taste and preference. YMMV
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
TheContext
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member inonCreate()
. How are you initializing the member, are you callinggetApplicationContext()
?
– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declarepublic static Context appContext;
. 2nd, in onCreate() initialize it:if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?
– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
|
show 1 more comment
This is one of the rare occasions where a globally accessible singleton class may be better than passing the Context
to every single class.
I would consider creating a singleton for localization, then use the Context
inside of there (unless you need other aspects of the Context
all over the place).
Of course, this is a matter of taste and preference. YMMV
This is one of the rare occasions where a globally accessible singleton class may be better than passing the Context
to every single class.
I would consider creating a singleton for localization, then use the Context
inside of there (unless you need other aspects of the Context
all over the place).
Of course, this is a matter of taste and preference. YMMV
edited Apr 14 '14 at 0:02
naXa
13.9k892137
13.9k892137
answered Sep 20 '11 at 19:21
Eric FarrEric Farr
2,4301627
2,4301627
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
TheContext
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member inonCreate()
. How are you initializing the member, are you callinggetApplicationContext()
?
– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declarepublic static Context appContext;
. 2nd, in onCreate() initialize it:if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?
– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
|
show 1 more comment
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
TheContext
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member inonCreate()
. How are you initializing the member, are you callinggetApplicationContext()
?
– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declarepublic static Context appContext;
. 2nd, in onCreate() initialize it:if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?
– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
There is no need to use a Singleton for localization. If you use the Context object, Android does it for you. Why reinvent the wheel with a Singleton that does the same thing?
– Austyn Mahoney
Sep 20 '11 at 21:02
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
@Austyn Mahoney Please explain how "Android does it for you"? I tend to accept Eric Farr's answer, by simply initializing a static Context member in Activity.OnCreate() because it simplifies implementation immensely. Do you have a better suggestion?
– uTubeFan
Sep 20 '11 at 21:57
The
Context
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member in onCreate()
. How are you initializing the member, are you calling getApplicationContext()
?– Austyn Mahoney
Sep 20 '11 at 22:06
The
Context
already has the localization features that the OP needs, why wrap it in a singleton? What do you mean by initializing a static Context member in onCreate()
. How are you initializing the member, are you calling getApplicationContext()
?– Austyn Mahoney
Sep 20 '11 at 22:06
@Austyn Mahoney Yup. 1st, declare
public static Context appContext;
. 2nd, in onCreate() initialize it: if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?– uTubeFan
Sep 20 '11 at 22:49
@Austyn Mahoney Yup. 1st, declare
public static Context appContext;
. 2nd, in onCreate() initialize it: if (appContext == null) appContext = getApplicationContext();
. This makes it available to all classes in the project... Any problem with that?– uTubeFan
Sep 20 '11 at 22:49
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
Discussions like this need to be moved to chat per SO policy. Let me know if you need my comment explained.
– Austyn Mahoney
Sep 21 '11 at 3:52
|
show 1 more comment
This is the Service locator pattern - you pass around a service locator (often called "Context") and get the required dependencies from it. It is not an anti-pattern, and is not that much of a bad design, but usually dependency injection is considered superior.
What you are doing is - passing the service locator even further down the object graph. What is advisable is to give each class only the dependencies it needs. So instead of passing Context
in the constructor, you pass all the strings it requires. That way you won't be violating the Law of Demeter
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
|
show 8 more comments
This is the Service locator pattern - you pass around a service locator (often called "Context") and get the required dependencies from it. It is not an anti-pattern, and is not that much of a bad design, but usually dependency injection is considered superior.
What you are doing is - passing the service locator even further down the object graph. What is advisable is to give each class only the dependencies it needs. So instead of passing Context
in the constructor, you pass all the strings it requires. That way you won't be violating the Law of Demeter
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
|
show 8 more comments
This is the Service locator pattern - you pass around a service locator (often called "Context") and get the required dependencies from it. It is not an anti-pattern, and is not that much of a bad design, but usually dependency injection is considered superior.
What you are doing is - passing the service locator even further down the object graph. What is advisable is to give each class only the dependencies it needs. So instead of passing Context
in the constructor, you pass all the strings it requires. That way you won't be violating the Law of Demeter
This is the Service locator pattern - you pass around a service locator (often called "Context") and get the required dependencies from it. It is not an anti-pattern, and is not that much of a bad design, but usually dependency injection is considered superior.
What you are doing is - passing the service locator even further down the object graph. What is advisable is to give each class only the dependencies it needs. So instead of passing Context
in the constructor, you pass all the strings it requires. That way you won't be violating the Law of Demeter
answered Sep 20 '11 at 19:20
BozhoBozho
486k1089541066
486k1089541066
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
|
show 8 more comments
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
2
2
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
I dont agree. KISS (keep it simple) is better principle in such cases.
– ggurov
Sep 21 '11 at 6:47
1
1
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
@Bozho - with Application as singleton you dont pass anything and it is simpler. Actually it is simpler in any case, because if you pass any strings, you should know what strings the other object uses. If you use context, you dont care how many and which strings any object needs. And thats OOP.
– ggurov
Sep 21 '11 at 8:12
1
1
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
and when you need to unit test the whole thing, you start mocking 'the whole world' :)
– Bozho
Sep 21 '11 at 8:21
2
2
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
Well, the last thing which I expected to hear here is that data encapsulation is bad and leads to "mocking the whole world". GL with your understanding of OOP.
– ggurov
Sep 21 '11 at 9:52
1
1
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
My previous comment was about data encapsulation. Strings which one object uses for showing messages to the user are its own stuff and it is bad practise to send them as parameters from someone else just because they are in the resources. From programmers viewpoint these strings belong to the object which uses them, not to its caller. The caller dont need to know anything about such things or soon the programmer will be completely lost in the code.
– ggurov
Sep 21 '11 at 10:29
|
show 8 more comments
Sending regularly contexts as parameters and remember them is dangerous, read here: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Much better is to subclass Application and to make singleton with it (the application object is context too). Such sollution doesn't have significant drawbacks.
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
add a comment |
Sending regularly contexts as parameters and remember them is dangerous, read here: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Much better is to subclass Application and to make singleton with it (the application object is context too). Such sollution doesn't have significant drawbacks.
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
add a comment |
Sending regularly contexts as parameters and remember them is dangerous, read here: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Much better is to subclass Application and to make singleton with it (the application object is context too). Such sollution doesn't have significant drawbacks.
Sending regularly contexts as parameters and remember them is dangerous, read here: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Much better is to subclass Application and to make singleton with it (the application object is context too). Such sollution doesn't have significant drawbacks.
answered Sep 20 '11 at 19:36
ggurovggurov
92121021
92121021
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
add a comment |
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
This is in line with @Eric Farr's suggestion. +1.
– uTubeFan
Sep 20 '11 at 21:00
add a comment |
I don't know if it's a bad practice to use it this way, but I did time comparison that took to load 200 light-weight object into Array-list with one of the Constructors taking Context as parameter, and other one getting the required context through static method like @Eric Farr suggested. End result was that accessing context through static method instead of passing to constructor was always 5-25% faster..
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initBlocks(map); // takes context through static method
blocks.clear();
initBlocks(getContext(), map); // pass context down to every block object
mainthread = new GameThread(getHolder(), this);
mainthread.setRunning(true);
mainthread.start();
}
I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects,
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects,
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects,
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects,
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms
I don't know about you, but I'll take an increase in performance (y).
add a comment |
I don't know if it's a bad practice to use it this way, but I did time comparison that took to load 200 light-weight object into Array-list with one of the Constructors taking Context as parameter, and other one getting the required context through static method like @Eric Farr suggested. End result was that accessing context through static method instead of passing to constructor was always 5-25% faster..
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initBlocks(map); // takes context through static method
blocks.clear();
initBlocks(getContext(), map); // pass context down to every block object
mainthread = new GameThread(getHolder(), this);
mainthread.setRunning(true);
mainthread.start();
}
I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects,
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects,
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects,
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects,
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms
I don't know about you, but I'll take an increase in performance (y).
add a comment |
I don't know if it's a bad practice to use it this way, but I did time comparison that took to load 200 light-weight object into Array-list with one of the Constructors taking Context as parameter, and other one getting the required context through static method like @Eric Farr suggested. End result was that accessing context through static method instead of passing to constructor was always 5-25% faster..
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initBlocks(map); // takes context through static method
blocks.clear();
initBlocks(getContext(), map); // pass context down to every block object
mainthread = new GameThread(getHolder(), this);
mainthread.setRunning(true);
mainthread.start();
}
I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects,
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects,
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects,
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects,
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms
I don't know about you, but I'll take an increase in performance (y).
I don't know if it's a bad practice to use it this way, but I did time comparison that took to load 200 light-weight object into Array-list with one of the Constructors taking Context as parameter, and other one getting the required context through static method like @Eric Farr suggested. End result was that accessing context through static method instead of passing to constructor was always 5-25% faster..
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initBlocks(map); // takes context through static method
blocks.clear();
initBlocks(getContext(), map); // pass context down to every block object
mainthread = new GameThread(getHolder(), this);
mainthread.setRunning(true);
mainthread.start();
}
I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects,
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects,
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects,
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects,
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms
I don't know about you, but I'll take an increase in performance (y).
answered Jan 1 at 4:12
CandlemanCandleman
111
111
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7490518%2fis-having-to-pass-context-to-most-classes-a-sign-of-bad-design%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It does feel a bit messy doesn't it...
– jondavidjohn
Sep 20 '11 at 19:17
@jondavidjohn Every design is a result of some compromise.
– uTubeFan
Sep 20 '11 at 19:18
2
I didn't like that Context-passing when I first saw the Android API
– Bozho
Sep 20 '11 at 19:28
@Bozho It gets worse: a package name is totally static at runtime, yet it requires Context to be read: stackoverflow.com/questions/2002288/…
– uTubeFan
Sep 20 '11 at 19:35
I disagree, I think the design works for what it was intended to do. The
Context
can be hard to keep track of sometimes, but it forces a better design from the developer. At least try to be constructive and add some reasoning when you post a comment.– Austyn Mahoney
Sep 20 '11 at 21:01