Huge java class for android project, how to split it up? - java

In C++ I'm used to being able to split classes up into multiple files using the scope resolution operator (::), but in java it seems impossible to split a class between multiple files.
I've read that classes shouldn't be more than a few hundred lines, but that sounds like ideological nonsense from people who don't write significant applications.
I am writing an industrial Android application (not for consumers, for technicians using professional test and measurement equipment in conjunction with the app linked via bluetooth) and several of my android activities are more than 1000 lines long and I'm not even close to being finished. The primary activity is over 6000 lines long and I expect it to become much longer still... It's becoming very unwieldy and, like I said, in C++ I would just logically split the class among multiple source files, but I guess that's not an option here.
Is there any alternative that I am overlooking to reduce the length of my source files without actually cutting out code (which is not an option...)?

It's acceptable to have a class with more than a hundred lines (most of my classes I write are more than 100 lines long). The thing is, dealing with an Object Orientated language, one should categorize as much as possible, to make the code maintainable, intuitive and readable. Good luck with your app!

You can subclass your class. Make a base class with core functionality and subclass it. So you can have several files and at the end you have just one class you can use.

you can still use composition and implementation techniques. The Java Package is the same as C++ Namespace

Why don't you try to separate common things in different classes, and then use instances of those classes on your Activities? Something like a command pattern, but a bit simpler.

Related

How to split a Java library source into two blocks, keeping one package?

We are creating an android library for use with Android. That means an Eclipse-like IDE and an Ant-like build process.
The nature of the library is that it has two distinct parts, representing different levels of abstraction - let's say 'upper' and 'lower'.
Assume, for the purposes of this question, that we need to call methods in one part from the other, but would like to keep those methods hidden from the library user. I've scoured the usual references but they all stop at the point of explaining package name conventions and scope rules. I've failed to find anything that answers this on SO, though this was useful.
The immediate solution is to simply have everything in one package and for those methods to be package-private. However, for reasons of maintainability, clarity, and not-having-100-files-in-one-folder we'd prefer to split the parts into different folders.
The obvious splitting point is to split the (let's say 'wibble') package into com.me.wibble.upper and com.me.wibble.lower packages/folders, but that makes any interconnecting methods undesirably public. In mitigation they could be hidden from the javadoc with #hide.
Another thought is whether could we split the parts at the top level and instead of the classic /main and /test folders have /upper, /lower and /test and all parts share the same com.me.wibble namespace. I'm unsure if/how Eclipse would cope with that.
Is there a conventional way of doing this, or is it just not done? If there are ways, what are the pro's and con's?
hmmm......Instead of asking for the solution, sometimes it is better to give the question. WHY you want library users to have a restricted view may generate a better answer than the HOWTO. There are a few answers I thought of but didn't give because I don't know the motivation behind the question (I don't want to waste your time with an answer that is not applicable).
/upper,/lower/,/test doesn't make your situation any nicer. It just makes the project more organized. Whether they are all in the same folder or separate it doesn't affect much.
It sounds like you need public 'interfaces' for library users while having private 'interfaces' for your own use. This is possible with hacking but can be painful if this is large pre-existing collection of code.

How to structure and organize nested classes

New to OOP, eager to learn good habits.
I want to make a vectorMap class. A vectorMap will have a few properties and contain a number of polyLine objects, which in turn will each will have a few properties and consist of a number of xyPoint objects.
The user will mostly interact with vectorMap objects, but may occasionally want to use polyLine and xyPoint objects outside the context of vectorMap.
Does this mean I should create three separate public classes? Would this mean three separate class modules in VBA, and in Java, three separate .java files?
My procedural gut tells me that it would be untidy to have three separate source code files for three small and simple classes with only a few lines of code each. I'm used to source code files containing packages with many functions. At this rate, a VBA project will contain tens of class modules. But maybe that's just the way it's done in OOP...
The above will be implemented in VBA and Java, so any examples in either/both of these are most welcome.
what do you mean "simple small classes"? My opinion is you should use a fresh file for each class which is testable. if (for instance) XyPoint is just a touple containing 2 elements, it will be a good idea to put it as a subclass of PolyLine.
However, as far as I see it - PolyLine and VectorMap should be in separate files, since you cannot really tell A is important only to B, and both are testable.
also, when using subclasses in java, notice their types (static/non-static,anonymous..) and choose wisely which is preferred.
p.s. a strong convention in Java is that class names start is a capital letters.
p.s.2: I assume this is done for educational purposes, otherwise you should (as #Ingo said) use built in classes, and not to reinvent the wheel...

Saving classes and objects to file (Java)

tldr: I'm new to programs with persistent data and am looking for the right way to save/load files. Can anyone point me in the right direction?
I undertaking a project which involves much saving and loading of files between two related systems. Simplified, there is one program which functions as the 'builder' for developers and another which is the 'interface' for clients.
In the 'builder', developers have the functionality to define Items and their possible properties which clients may interact with in the interface. For example, the developer may make an Item called 'car' which may have colour, model, and speed properties; and also an item called 'house' which has dimensions, colour. He can make any number of items, which may be diverse and each will have a few common properties (name, colour) and also an array of different properties.
In the 'interface', clients may choose any number of items into their world. Ie, they may take 2 cars and 1 house, and separately define their properties such that one of the cars is a Fast Red Hotrod, another is a Slow White Van, and the house is Brown and 3x2.
both Car and House are instances of Item, but the client has further specified 2 different instances of Car.
Currently I have saving the different instances (car, house etc) into text files and this seems to be working well, but I'm sure there must be a better way (particularly as I intend the client interface to be runnable on Android). Can anyone point me in the right direction (s) or to some material which would help me make the choice?
One option is to use Java binary serialization. I would personally avoid that option.
There are plenty of other serialization frameworks around. For example, I've ported Google's Protocol Buffers framework to C#, so I'm generally biased in favour of that - but there are lots of other options too, such as:
XML
JSON
Thrift
These options generally have advantages in terms of:
Portability to other platforms (consider if you want to build an iPhone or Windows Phone 7 app in the future)
Backward and forward compatibility
Human readability (or easy conversion to a human format)
Some of them are very compact, too
Admittedly Java binary serialization makes the easy path very easy when it's working - but it can be a pain in other ways. Just my experience.
Databases are excellent places to put persistent data.
You can use Serialization. You'll need to check how you'll access the file/convert on Android.

How to refactor legacy code effectively and efficiently? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
What should I keep in mind in order to refactor huge code base?
When is it good (if ever) to scrap production code and start over?
I am currently working with some legacy source code files. They have quite a few problems because they were written by a database expert who does not know much about Java. For instance,
Fields in classes are public. No getters and setters.
Use raw types, not parameterized types.
Use static unnecessarily.
Super long method names.
Methods need too many parameters.
Repeat Yourself frequently.
I want to modify them so that they are more object-oriented. What are some best practices and effective/efficient approaches?
Read "Working Effectively with Legacy Code" by Michael Feathers. Great book - and obviously it'll be a lot more detailed than answers here. It's got lots of techniques for handling things sensibly.
It looks like you've identified a number of issues, which is a large part of the problem. Many of those sound like they can be fixed relatively easily - it's overall design and architecture which is harder to do, of course.
Are there already unit tests, or will you be adding those too?
Before you start, create a system-level regression test suite for the application. You need this so that you can verify that your changes don't break things.
To do the refactoring, you want a use a combination of a good IDE, and text search tool (e.g. grep). Use the text search tool to find occurrences of the "syndromes" that you want to fix, then use the IDE (and its builtin refactoring capabilities) to fix the instances ... one at a time.
For example, Eclipse allows you to rename a method or class, or generate getters and setters. So you'd cure a 'public' attribute by:
Change the attribute to private.
Generate the getter and setter methods.
Save the file.
Go through all of the Java compilation errors resulting from the fact that the attribute is now private, and change to use the getter or setter as appropriate.
This approach will give you the low-hanging fruit. More fundamental design issues are more difficult, and may be impossible to fix without fundamental restructuring of the application. The refactoring capabilities will help you execute such changes, but deciding what to do is ultimately up to you.
Finally, my advice is to not be too ambitious. Go for incremental improvement, and be prepared to draw the line when the code is "good enough". You won't achieve perfection ... not even if you start from a clean slate ... so don't set your expectations high.
Is it just the code that is bad, or does it also hurt the user experience? Refactoring continuously is a good idea, but it should not be a goal unto itself. It should improve the application in terms of user interaction, maintainability, stability, performance, etc.
That is why I am not extremely fond of huge refactoring just to improve the code quality. Instead, refactor the code that you work with.
While working with a legacy system for several years, I have personally found that:
Create for yourself a vision of how you want the code after you're done. It should be attainable, contain a list of technology changes, general architecture changes. It may also be a good idea to make a rough priority of what classes are most critical to change. We lacked such a vision a few years ago, and while we refactored a lot, the code quality barely improved.
Now, you should restrict your refactoring to those that make you reach your vision. Don't fall into the trap of doing what appears good at the moment.
Focus on a particular component, and make it better. Then move on to the next. It's tempting to make huge changes that affect the entire system, but in truth you will introduce more problems than you solve.
Write integration regression tests. I.e., a few big tests that test a lot of functionality. It's not optimal, but it's the best you can do. Writing unit tests for every single class in your old system may end up a waste of time because it's not designed to be tested anyway and you want to redesign half of the classes.
Accept that it will take time.
Eclipse should be able to take care of #1 and help you work your way through many of the others.
As for converting poor OO code to good OO code it is amazingly difficult. Often it seems easier to rewrite it from scratch.
I tend to go from the bottom up. As I'm working on some small section I'll recognize a bunch of data that belongs together as a group and I'll make a good object that replaces that code without changing anything else--Very Small Changes with constant tests between each change.
This makes for a mediocre design at best, but I honestly don't know if you can go from not OO to good OO on a large project without dissecting the original program, understanding it and using it as a template for the rewrite and few projects allow this (even though it might be faster, you'll rarely if ever be able to convince management of that fact)
The point is risk I think.
The ugly code is just ugly, but it could work, it has been tested and bugfixed. If runnable code is changed, risk will follow. so test is critical.
You could refactor related code when
you have to bugfix, as a conservatism solution.
Maybe the first challenge is to persuade your manager:)
What's the problem with it not having getters and setters? I'd suggest refactoring those only when you need to add non-trivial getters or setters (e.g., with validation).
The rest sounds like you need to identify groups of values and create new types holding them, so instead of passing a String name, String address, int yearOfBirth, String[] accountNames, int[] balances you would pass a Customer around, which would in turn have an Account[].
IDEA Ultimate Edition has a code duplication detector that's very good (it's only missing a 'suggested solution' button!), and there are CPD etc.
I'd suggest that in a large legacy codebase you might waste time refactoring code only to find out it wasn't used anyway. I outlined some steps for removing unused code: http://rickyclarkson.blogspot.com/2009/12/deleting-code-what-first.html
How many of those "issues" are real problems and not just matters of style? Of this list, the only 'real' issue I can see is "Repeat Yourself frequently", and that's more of an ongoing maintenance problem that should be resolved during normal code maintenance when someone's going to be changing the code anyway.
I want to modify them so that they are more object-oriented.
Object-Orientation should not be your only goal when refactoring. The question you should ask yourself is what is the expected ROI (better quality ? easier enhancements ? better sharing of this code across a team ?) A ROI is not just words, you should be prepared to measure with numbers the return on investment (even the quality enhancements for example). You should take into accounts the life duration of your products in estimating the ROI.
You should also ask yourself what is the size of the code which is dependent on the code you want to refactor. Refactoring a library could be easy but could lead to a lot of changes in source codes dependent on this library, a work well larger than just refactoring the library.
Before touching any code, you should estimate the total work that needs to be done to finish refactoring the code and dependent code. You should estimate a total rewrite of the code, a partial rewrite, or just an internal rewrite without touching APIs.
With the costs and returns, you could decide if it's worth the effort to refactor your code.

how many classes per package? methods per class? lines per method?

I have to give a general note to some huge Java project for which I have but little visibility and I was wondering if there were any guidelines for determining:
what number of classes per package can be considered right, to low, or to high (this project has 3.89 classes per package, which seems a bit too small for me),
number of methods per class? (this project has 6.54 methods per class...
number of lines per method? (this project has about 7 lines per method (seems pretty good to me, maybe a bit low))
I should note that this question is only dealing with volumetry. I have a bunch of reports from quality tools (checkstyle, jdepend, cpd, pmd, ncss) that give me more vision about code redundancy, classes usage, bugs, etc.
Steve McConnell in his book Code Complete recommends about 7 methods per class and no more lines in a method then can be viewed in a single screen without scrolling.
I'm not sure about classes per package.
I would highly recommend reading Code Complete for more information on such topics.
I think stats like that are pretty useless, how does knowing the lines per method show whether its any use to the project or not; i think you should be looking more along the lines of:
Do your packages encompass like
classes?
Do your classes work as an
entity on their own?
Do the methods
within the classes function
correctly and efficiently?
Surely other than memory usage, it doesn't matter whether the method is large or not? the other thing to look for in very protracted methods is whether the stack trace is going to be bigger than adding that functionality to a parent method. I'd be wary of measuring a projects success based on the lines of code.
Robert C. Martin, who recently released the book "Clean Code", states that the number of lines per method should be the absolutely smallest possible. Between 1-7 lines is a good rule of thumb.
There's also a good point being made in the book The ThoughtWorks Anthology, in the essay “Object Calisthenics” by Jeff Bay. He suggests 9 pretty hardcore constraints that will make you a better OO developer in the long run. Read more about them here.
To answer your specific questions, these are the constraints specifically to you:
- No more than 10 classes per package
- A maximum of 50 lines per class
These constraints might not be ideal for all of your real projects, but using them in a small (hobby?) project will force you into a better practice.
Unfortunately, there's no absolute (objective) notion of quality in software. Thus, there's no "right" value for these. However, here are a two (personal) obsevations:
3.89 classes/package is very low. It means you'll be battling through a complicated tree of packages.
7 Lines per method: Indeed sounds good. However, if these number was arrived at as a result of an intentional effort to reduce the line count of methods then you might have ended up with a single logical task being spread around several private methods which will make it more difficult to understand the class (in certain cases). Actually in CodeComplete-2, the author cites a research which discovered that method length is much less importance than its cyclomatic complexity and its nesting level.
A useful design guideline says that each class should only do one thing and do it well. This will not give you a fixed number of methods per class, but it will limit the number and make the class easier to comprehend and maintain.
For methods you can adopt a similar view and aim for methods that are as small as possible, but no smaller. Think of it this way: if you can split the method into two or more distinct parts it is obviously not as small as it could be. Small methods are easy to understand and by splitting the code like this you will get a better overview in high level methods and push details to low level methods.
(note: tl;dr available at the very bottom for my real opinion)
I'm not going to quote any big name and say that's the right answer because it's always very case dependant how you do all this stuff. For example the number of methods: If you're making a control software for modern HD LCD TV's remote controller which has about 40-50 buttons, how can you break that down into classes coherently so that you only have like, say, 7 methods per class?
Personally I like to keep all the methods of one accessor level in one class which means some utility classes may end up having hundreds of methods but in my opinions it's easier to do something like StringUtil.escapeXMLspecialCharacters(someString) than StringUtil.XML.escapeSpecialCharacters(someString) or XMLUtil.escapeSpecialCharacters(someString). While these all are seemingly OK solutions, the first one thrives (at least in my mind, that is!) because it's simple and very easy way to access that method: You don't have to think if the string you're handling contains XML or XHTML or JSON or whatever, you'll just pick one method from the general group of methods and that's it.
Keeping on the previous TV remote analogy, lets assume you do split them to various classes anyway. If we allow ourselves to have 7 of such methods per class on average and manage to group the buttons on the remote to sensical groups like MenuButtons, AdjustmentButtons and 'NumberSelectorButtons', we end up with 8 or so classes. That's not a bad thing actually, but it gets slightly confusing easily especially if they're not divided to sensical groups with great care. Just imagine the rants around your TVRemotes'R'Us Inc. office: "Who says the power on/off button is a control button?" "Who's the joker who put volume +/- to menu buttons? PRE/CH (the button which switches between current and previous channel and/or image source) button isn't a number button!" "The guide button opens both tv guide AND navigational menu depending on context, what are we going to do with it!?"
So as you can hopefully see from this example, using some arbitrary number to limit yourself could introduce some unneeded complexity and break the logical flow of the application.
Before I throw in my last two cents, one thing about the number of lines per method: Think code as blocks. Each loop is a block, each conditional is a block and so on and so forth. What is the minimum amount of these blocks needed for a unit of code which has a single responsibility? That should be your limiter, not the desire to have "Seven everywhere." from number of classes in package, methods in classes and lines of code in methods.
And here's the TL;DR:
So, my real opinion is actually this: The number of classes in package should be fairly low. I've been lately starting to do the following but I'm not sure if I'll keep up to it:
Package foo contains interfaces and other common classes for implementations.
Package foo.bar contains implementation of said interfaces for function bar
Package foo.baz contains implementation of said interfaces for function baz
This usually means my whole structure has a coherent (and most likely low) number of classes and by reading the top level class interfaces (and their comments) I should be able to understand the other packages too.
Methods per class: All which are needed as I explained above. If your class can't live without 170 methods, then let it have them. Refactoring is a virtue, not something that can be applied all the time.
Lines per method: As low as possible, I usually end up with 10 to 25 lines per method and 25 is a bit high for me so I'd say 10 is a good balance point for that.

Categories