I am working on a large code base that was written 90% in Java and 10% in Groovy. I only started learning Groovy recently and would like some advice. I have come across code like this in a Groovy method:
throw new RuntimeException(getErrorMessage(state));
This works most of the time. The problem is that on this very rare occasion, getErrorMessage(state) returned null instead of a String. I cannot change the implementation of getErrorMessage().
I can fix this particular issue like this:
throw new RuntimeException((String) getErrorMessage(state));
or like this:
throw new RuntimeException(getErrorMessage(state) ?: '(no detail available)');
This issue would not arise if I used #CompileStatic, but there are other parts of the code that rely on dynamic features.
My problem is that I can only fix such issues by coming across them as a result of a bug report, which is not good for the application's reliability and reputation. (Also the problem is not just with getErrorMessage but with all possible situations in which an ambiguous overload exception can happen at runtime.)
How can I foresee such issues beforehand? (Currently available static analysis tools don't seem to be clever enough to catch this.)
Do a search for all getErrorMessage() and replace them for myGetErrorMessage():
public String myGetErrorMessage(int state) {
return getErrorMessage(state) ?: '(no detail available)';
}
Aspect-Oriented Programming may be overkill for this particular case, but it will get you what you want. You will still need to somehow identify all the methods that need intervention. This is an article describing several AOP libraries.
Related
According to the occurrence of questions about 'AutoMapper Migraton from static API' lately and the fact I was Exploring Christos Sakell blog 'Building Single Page Applications using Web API and AngularJS', I also came across some obsolete warnings.
/***********************************************************************************
* AutoMapper.Mapper.CreateMap()' is obsolete: 'Dynamically creating maps will be removed in version 5.0.
* Use a MapperConfiguration instance and store statically as needed, or Mapper.Initialize.
* Use CreateMapper to create a mapper instance.
***********************************************************************************/
Completely ignorant of recent changes of AutoMapper (I using this mapping tool for the very first time) I was trying to get rid of those obsolete messages. Searching around I came across two possible solutions:
1) http://quabr.com/36398318/automapper-mapper-createmaptsource-tdestination-is-obsolete , and
2) http://davecallan.com/automapper-4-2-example/#comment-8914
These hints seemed to be pretty straightforward. It turned out tweaking the *MappingProfile classes weren't that difficult, but what to do on several controllers? That was a complete different piece of cake. I got completely lost. I ran in all kind of strange errors not knowing or having a clue what to do. Even the just mentioned blogs weren’t that explanative. More or less, I got the feeling they were keeping the puzzle a live (I'm kidding).
So the question was: how to solve the troublesome mapping from the controller to the *MappingProfile class. Luckily, I found a possible solution, so please tackle it...
I do like puzzling and buzzing around the net, I finally found a combination of hints, and that's what I want to share with you.
The solution for this is a combination of tweaks.
First of all, have a look at page 'Migrating from static API' (https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API).
Notice the second block right below ‘In 4.2.x and later …’ that’s what is needed on several controllers. Dave Callan just gave a part of the clue. He just forgot a part of the solution. So I asked him to add the missing part to his solution as well.
So, implementing the hint on the 'Migrating from static API' page in combination with the suggestion of Dave Callan (http://davecallan.com/automapper-4-2-example/#comment-8919) block 1: Instantiating a new MapperConfiguration(...) in *MappingProfile class(es), you can get rid of those obsolete warnings: On every cycle proper mapping.
At least, I got rid of those warnings.
What will happend in the nearer future with AutoMapper, hopefully those guys in Austin TX will make proper decisions on this matter.
I also testing the code (block 2 of 'Migration from static API') with the suggestion on Quabr (instead of instantiating a new MapperConfiguration, they suggest to call the Initialize method of the current Mapper). This combination gave my errors like ‘index outside matrix borders’.
Apparently on each cycle the mapping lists are not renewed. This combination of code tweaks resulted (to me) in a ‘no go’. Perhaps others, do not agree with me, fine, at least that’s what I noticed.
My only goal is to help other members who are facing comparable trouble.
I'm pleased to share my solution. Have fun
First, I have to say that I really like Groovy and all the good stuff it is bringing to the Java dev world. But since I'm using it for more than little scripts, I have some concerns.
In this Groovy help page about dynamic vs static typing, there is this statement about the absence of compilation error/warning when you have typo in your code because it could be a call to a method added later at runtime:
It might be scary to do away with all of your static typing and
compile time checking at first. But many Groovy veterans will attest
that it makes the code cleaner, easier to refactor, and, well, more
dynamic.
I'm pretty agree with the 'more dynamic' part, but not with cleaner and easier to refactor:
For the other two statements I'm not sure: from my Groovy beginner perspective, this is resulting in less code, but in more difficult to read later and in more trouble to maintain (can not rely on the IDE anymore to find who is declaring a dynamic method and who is using one).
To clarify, I find that reading groovy code is very pleasant, I love the collection and closure (concise and expressive way of tackle complicated problem).
But I have a lot of trouble in these situations:
no more auto-completion inside 'builder' using Map (Of Map (of Map))
everywhere
confusing dynamic methods call (you don't know if it is a typo or a
dynamic name)
method extraction is more complicated inside closure (often resulting in code duplicate: 'it is only a small closure after all')
hard to guess closure parameters when you have to write one for a method of a subsystem
no more learning by browsing the code: you have to use text search instead
I can only saw some benefits with GORM, but in this case the dynamic method are wellknown and my IDE is aware of them (so it is more looking like a systematic code generation than dynamic method for me)
I would be very glad to learn from groovy veteran how they can attest of these benefits.
It does lead to different classes of bugs and processes. It also makes writing tests faster and more natural, helping to alleviate the bug issues.
Discovering where behavior is defined, and used, can be problematic. There isn't a great way around it, although IDEs are getting better at it over time.
Your code shouldn't be more difficult to read--mainline code should be easier to read. The dynamic behavior should disappear into the application, and be documented appropriately for developers that need to understand functionality at those levels.
Magic does make discovery more difficult. This implies that other means of documentation, particularly human-readable tests (think easyb, spock, etc.) and prose, become that much more important.
This is somewhat old, but i'd like to share my experience if someone comes looking for some thoughts on the topic:
Right now we are using eclipse 3.7 and groovy-eclipse 2.7 on a small team (3 developers) and since we don't have tests scripts, mostly of our groovy development we do by explicitly using types.
For example, when using service classes methods:
void validate(Product product) {
// groovy stuff
}
Box pack(List<Product> products) {
def box = new Box()
box.value = products.inject(0) { total, item ->
// some BigDecimal calculations =)
}
box
}
We usually fill out the type, which enable eclipse to autocomplete and, most important, allows us to refactor code, find usages, etc..
This blocks us from using metaprogramming, except for Categories which i found that are supported and is detected by groovy-eclipse.
Still, Groovy is pretty good and a LOT of our business logic is in groovy code.
We had two issues in production code when using groovy, and both cases were due bad manual testing.
We also have a lot of XML building and parsing, and we validate it before sending it to webservices and the likes.
There's a small script we use to connect to an internal system whose usage is very restricted (and not needed in other parts of the system). This code i developed using entirely dynamic typing, overriding methods using metaclass and all that stuff, but this is an exception.
I think groovy 2.0 (with groovy-eclipse coming along, of course) and it's #TypeChecked will be great for those of us that uses groovy as a "java++".
To me there are 2 types of refactoring:
IDE based refactoring (extract to method, rename method, introduce variable, etc.).
Manual refactoring. (moving a method to a different class, changing the return value of a method)
For IDE based refactoring I haven't found an IDE that does as good of a job with Groovy as it does with Java. For example in eclipse when you extract to method it looks for duplicate instances to refactor to call the method instead of having duplicated code. For Groovy, that doesn't seem to happen.
Manual refactoring is where I believe that you could see refactoring made easier. Without tests though I would agree that it is probably harder.
The statement at cleaner code is 100% accurate. I would venture a guess that good Java to good Groovy code is at least a 3:1 reduction in lines of code. Being a newbie at Groovy though I would strive to learn at least 1 new way to do something everyday. Something that greatly helped me improve my Groovy was to simply read the APIs. I feel that Collection, String, and List are probably the ones that have the most functionality and I used the most to help make my Groovy code actually Groovy.
http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html
http://groovy.codehaus.org/groovy-jdk/java/lang/String.html
http://groovy.codehaus.org/groovy-jdk/java/util/List.html
Since you edited the question I'll edit my answer :)
One thing you can do is tell intellij about the dynamic methods on your objects: What does 'add dynamic method' do in Groovy/IntelliJ?. That might help a little bit.
Another trick that I use is to type my objects when doing the initial coding and remove the typing when I'm done. For example I can never seem to remember if it's .substring(..) or .subString(..) on a String. So if you type your object you get a little better code completion.
As for your other bullet points, I'd really need to look at some code to be able to give a better answer.
When writing code, I find it important that my code looks well (apart from the fact that it has to work well). It is well described in the book Code Complete (p729): 'The visual and intellectual enjoyment of well-formatted code is a pleasure that few nonprogrammers can appreciate'.
The problem is, as soon as I got my code functionally working, and I start to introduce error handling (try-except clauses etc.) to make it robust, I find that this usually messes up my well-laid out code and turns it into something that is definitely not visually pleasing. The try-except statements and additional if's, make the code less readable and structured.
I wonder if this is because I misuse or overuse error handling, or is this unavoidable?
Any tips or tricks to keep it good-looking?
It is hard to give you a general answer for this, since there are a lot of different cases of error handling and so there are a lot of different approaches to deal with this problem. If you would post some real-world examples, you probably would get a lot of suggestions here on SO how to improve your code.
In general, adding error handling to existing functions makes them bigger, so refactoring them up into smaller methods is always a good idea. If you are looking for a more general approach, you should make yourself comfortable with Aspect-Oriented programming. That is an approach to keep out the code for so-called cross cutting concerns (like error handling) completely out of your business logic code.
EDIT: Just one simple trick:
I avoid writing error-checks like this:
int MyFunction()
{
if( ErrorCheck1Passes())
{
if( ErrorCheck2Passes())
{
if( ErrorCheck3Passes())
{
callSomeFunction(...);
}
else
return failureCode3;
}
else
return failureCode2;
}
else
return failureCode1;
return 0;
}
I prefer
int MyFunction()
{
if( !ErrorCheck1Passes())
return failureCode1;
if( !ErrorCheck2Passes())
return failureCode2;
if( !ErrorCheck3Passes())
return failureCode3;
callSomeFunction(...);
return 0;
}
I often wrap up chunks of code that require error handling into their own functions that will handle all possible exceptions internally, and so in a sense always succeed. The code that calls them looks cleaner, and if those functions are called more than once, then your code also becomes smaller.
This can make more sense if you are working more at the front end of an application, where from the user's point of view not every single possible exception needs to bubble up to their level. It's fine in the context of some classes for there to be a robust internal way of handling errors and moving on.
So for example, I might have functions like
SaveSettingsSafe();
// 'Safe' in the sense that all errors are handled internally before returning
You have rediscovered a major reason that Don Knuth invented literate programming: it is all too common for error handling to obscure the main algorithm. If you're lucky, you'll have some language constructs that offer you some flexibility. For example, exceptions may let you move the error handling elsewhere, or first-class functions may make it possible to move error handling around and reduce if-then-else checks to a function call.
If you're stuck in a language without these features, like C, you might want to look into a literate-programming tool. Literate-programming tools are preprocessors, but their whole mission is to help you make your code more readable. They have a small but rabid following, and you'll be able to find some guidance on the web and in published papers.
It all depends on how you do your programming. You can avoid a lot of these try-catch (or as you put it, try-except) statements if you just do proper input validation. Sure, it's a lot of work to cover most of the junk users tend to put into forms etc, but it will keep your data handling routines clean (or cleaner).
Is there a workaround for implementing cross cutting concerns without going into aspects and point cuts et al.?
We're in Spring MVC, and working on a business app where it's not feasible to go into AspectJ or Spring's aspect handling due to various reasons.
And some of our controllers have become heavily bloated (too heavily), with tons of out-of-focus code creeping in everywhere.
Everytime I sit down to refactor, I see the same things being done over and over again. Allow me to explain:
Everytime I have to prepare a view, I add a list of countries to it for the UI. (Object added to the ModelAndView). That list is pulled out of a DB into ehCache.
Now, initially it was terrible when I was trying to add the lists INLINE to the mav's everywhere. Instead, I prepared a function which would process every ModelAndView. How? well, with more garbage calls to the function!
And I bought out one trouble for another.
What's a design pattern/trick which can help me out a bit? I'm sick of calling functions to add things to my ModelAndView, and with over 3500 lines of only controller code, I'm going mad finding all the glue points where things have gone missing!
Suggestion are welcome. Cross cutting concerns flavor without AspectJ or Spring native.
Since you are using Java, you may consider moving your code to Scala, since it interacts well with Java, then you can use traits to get the functionality you want.
Unfortunately cross-cutting is a problem with OOP, so changing to functional programming may be a solution, but, I expect that in actuality they are using AOP to implement these mixins, so it would still be AOP, just abstracted out.
The other option is to look at redesigning your application, and make certain that you don't have duplicate code, but a major refactoring is very difficult and fraught with risk.
But, for example, you may end up with your ModelAndView calling several static utility classes to get the data it needs, or do ensure that the user has the correct role, for example.
You may want to look at a book, Refactoring to Patterns (http://www.industriallogic.com/xp/refactoring/) for some ideas.
What are some ways in which I can write code that is easily modified?
The one I have learned from experience is that I almost always need to write one to throw away. That way I have developed a sense of the domain knowledge and program structure required before coding the actual application.
The general guidelines are offcourse
High cohesion, low coupling
Dont repeat yourself
Recognize design patterns and implement them
Dont recognize design patterns where they are not existing or necassary
Use a coding standard, stick to it
Comment everyting that should be commented, when in doubt : comment
Use unit tests
Write comments and tests before implementation, that way you know exactly what you want to do
And when it goes wrong : refactor, refactor, refactor. With good tests you can be sure nothing breaks
And oh yeah:
read this : http://www.pragprog.com/the-pragmatic-programmer
Everything (i think) above and more is in it
I think your emphasis on modifiability is more important than readability. It is not hard to make something easy to read, but the real test of how well it is understood comes when someone else (or you) has to modify it in repsonse to changing requirements.
What I try to do is assume that modifications will be necessary, and if it is not really clear how to do them, leave explicit directions in the code for how to do them.
I assume that I may have to do some educating of the reader of the code to get him or her to know how to modify the code properly. This requires energy on my part, and it requires energy on the part of the person reading the code.
So while I admire the idea of literate programming, that can be easily read and understood, sometimes it is more like math, where the only way to do it is for the reader to buckle down, pay close attention, re-read it a few times, and make sure they understand.
Readability helps a lot: If you do something non-obvious, or you are taking a shortcut, comment. Comments are places where you can go back and refactor if you have time later. Use sensible names for everything, makes it easier to understand what is going on.
Continuous revision will let you move from that first draft to a better one without throwing away (too much) work. Any time you rewrite from scratch you may lose lessons learned. As you code, use refactoring tools to eliminate code representing areas of exploration that are no longer needed, and to make obvious things that were obscure. The first one reduces the amount that you need to maintain; the second reduces the effort per square foot. (Sqft makes about as much sense as lines of code, really.)
Modularize appropriately and enforce encapsulation and separation of logic between your modules. You don't want too many dependencies on any one part of the code or that part becomes inherently harder to understand.
Considering using tried and true methods over cutting edge ones. You give up some functionality for predictability.
Finally, if this is code that people will be using before and after modification, you need(ed) to have an appropriate API insulating your code from theirs. Having a strong API lets you change things behind the scenes without needing to alert all your consumers. I think there's a decent article on Coding Horror about this.
Hang Your Code Out to D.R.Y.
I learned this early when assigned the task of changing the appearance of a web-interface. The code was in C, which I hated, and was compiled to a CGI executable. And, worse, it was built on a library that was abandoned—no updates, no support, and too many man-hours put into its use to change it. On top of the framework was a disorderly web of code, consisting of various form and element builders, custom string implementations, and various other arcane things (for a non-C programmer to commit suicide with).
For each change I made there were several, sometimes many, exceptions to the output HTML. Each one of these exceptions required a small change or improvement in the form builder, thanks to the language there's no inheritance and therefore only functions and structs, and instead of putting the hours in the team instead wrote these exceptions frequently.
In my inexperience I was forced to change the output of each exception, rather than consolidate the changes in an improved form builder. But, trawling through 15,000 lines of code for several hours after ineffective changes would induce code-burn, and a fogginess that took a night's sleep to cure.
Always run your code through the DRY-er.
The easiest way to modify a code is NOT to write code. Write pseudo code not just for algo but how your code should be structured if you are unsure.
Designing while writing code never works...for me :-)
Here is my current experience: I'm working (Java) with a kind of database schema that might often change (fields added/removed, data types modified). My strategy is to parse this schema and to generate the code with apache velocity. The BaseClass generated is never modified by the programmer. Else, a MyClass extends BaseClass is created and the logical components of this class (e.g. toString() ! )are implemented using the 'getters' and the 'setters' of the super class.