In the structured programming world, when things got messy your code became SpaghettiCode. Everyone knows what SpaghettiCode is. It has been said that with objects you get RavioliCode: thousands of little classes everywhere and no one knows how to find the places where things really happen.
It seems that if you refactor the XP way, you start getting RavioliCode... perhaps less commonly because you are also deleting code and you only make/bake what you need.
I just want to know what you all think... is RavioliCode a problem? We work well with chunks of 7 +/- 2. I know my tolerance has increased over time, but walking into Ravioli is intimidating when there is no one around to show you the ropes.
RavioliCode threatens to bite: this style maximizes maintainability by old hands at the expense of comprehensibility by newcomers. The "HireOffTheRack?, give 'em the sack" management techniques assume that the temps can come in the door and get immediate traction. If they don't, this isn't gonna work...
This is where SystemMetaphor(s), Patterns and other explicit descriptions of architecture come in. Ravioli is only unmanageable when there's no way to see its symmetries and CommonSense.
There are a few reasons I believe you do not get RavioliCode when using XP. I'm sure there are more so I will encourage others to add their arguments as well.
Although it often does, I don't think RavioliCode always means that something needs fixing. In OO programming, there seems to be a trade-off between "easy to change" code and "easy to understand at first glance" code. You can try to maximize ease-of-change, then do your best to make the code understandable; or you can try to maximize understandability. I do the former. -- StanSilver
YouArentGonnaNeedIt helps avoid unnecessary ravioli. Ravioli comes from making fine distinctions, and we often see distinctions which aren't really relevant yet. OnceAndOnlyOnce helps cut out duplicated, redundant chunks, which tends to cull small chunks more than big ones (I think?).
Both tend to reduce the amount of code, which obviously will reduce the amount of ravioli in proportion, but I sort of feel they do better than that - that they attack ravioli disproportionately. Is that right? -- DaveHarris
Yes. I'm tending to think that RavioliCode is good, for the reasons that Stan mentioned. It is interesting to think of where this might break down. Do some systems end up with so many small chunks that they become too hard to understand?
I think the goal is to have recursive Ravioli. Have only the 7 +/- 2 top level Raviolis. Those contain other Raviolis as member object and delegate responsibility to them, and so on. So, at each level of containment, you have a smaller batch of Raviolis to deal with and understand at one time. -- GregVaughn
I think that last question is the key here. When there are so many small chunks that the system becomes hard to understand is when you have achieved RavioliCode. I don't think that just having lots of small chunks is bad if that's what the design calls for and those chunks are understandable in the context of the application. But if that's the case, then in my opinion you don't have RavioliCode, just appropriately factored code. So I think we're agreeing here; its just a matter of the definition of what we were thinking RavioliCode really meant. -- TomKubit
See ReadingRavioli for a suggestion that effective reading of RavioliCode is a learned behavior, because each method says more about the algorithm and less about the implementation than procedural code.
If you are refactoring within a strongly layered mental model, is that LasagnaCode? :)
I thought that LasagnaCode was a synonym for AlternateHardAndSoftLayers...
See also RavioliWiki, http://www.gnu.org/fun/jokes/pasta.code.html
If you have a nearby CS library, look up GuySteele's Macaroni is better than spaghetti in "Proceedings of the Symposium on Artificial Intelligence and Programming Languages", August 1977, pages 60-66.
I can't believe there's no mention here of BigBallOfMud http://www.devcentre.org/mud/bigballofmud.htm !
I love RavioliCode. I don't care about grokking the whole thing if it works, and the automated tests tell me if that's true. When it breaks the automated tests tell me where to look and the Ravioli nature makes it easy to understand that piece. Long ago I gave up on understanding everything and got used to understanding just enough to get by.
Related: CodeBrowserAsExcuseForMess
See also ShortMethods, BelievingAbstractions
My pain with RavioliCode is opening some code I downloaded to find a hundred little classes and with little methods that have been boiled down to the point that none of them actually seem to do anything. Ok, this method increments a variable. Blindingly clear, has a unit test, but so what? How do we point readers like me to the nut of the thing, some method with beautiful "coding by intention" that tells me what this fool program DOES?
Stop reading the code and read the method and class names instead, don't bother stepping into the method. The logic/nut you want isn't in the code anyway, it's in the relationships between the classes and messages/methods.
How do you find the nut of the thing with non-ravioli code?
Use the techniques mentioned in TipsForReadingCode and ReadingRavioli.
I don't see how ravioli code makes it harder to apply TipsForReadingCode.
Some survival tips:
For Java, use javadoc and look at the class tree, for crying out loud. DON'T just start groveling through the actual source if you are not yet familiar with it. (consideration for others: add some meaningful comments for javadoc to find) Along the "consideration" line of thought: Name the "program entry point" something conspicuous. For stand-alone executables, I usually call it Main, so the startup executes "Main.main()". It makes it easy to find. Any ideas on how to make servlets more apparent? (I guess you could find classes that implement the servlet interface) - R R Anderson
For a great example of RavioliWare gone bad, take a look at Apache Jetspeed portal. This humongous item of bloatware, which runs on Tomcat-Jakarta, can bring a dual Pentium4 with 2GB of memory to its knees!
I recall trying to extend the login function, just so that I could validate the login against a second database of staff members and add a flag to say "current employee". It took a day to dig down through 12 layers of objects, some in 3rd party libraries whose source was hard to find, before I actually found the bit which actually did stuff.
Coming from an embedded software on low-powered CPUs, I occasionally wonder whether OO is going to have to be reinvented to make the programmers more accountable for
RavioliCode can be caused by disguised GlobalMethods?. The giveaway in java is when you see this:
Foo foo = new Foo(); Bar barValue = foo.someMethod(someArgs, ...);The someMethod method has no relation to the state of the foo object at all. Even if it is not declared static, it may as well be. Foo, ultimately, is nothing but a bucket for some global source code.
This, perhaps, should be a CodeSmell ... I just need a snappy name for it. StatelessObject, perhaps.
What if the Foo object initializes private variables based on aspects of the current state of the system, and someMethod's return value is affected by those variables?
Then Foo seems to read global variables (or system configuration files), is dependent on those global variables, and isn't as simple as it could be.
It is suggested that a remedy to RavioliCode is a UnifiedDataModel. -- MarkJanssen
I'm confused, are we talking about cheese ravioli code or beef ravioli code? ;-)
{I hope it's cheese. I'm a vegetabilist of the pescetarian variety and avoid red meat.}
Oh, it's beef, but with a unified data model, it will be pure vegan. :)
A type of PastaCode.
See Also: BigSoupOfClasses