Ravioli Code

In the structured programming world, when things got messy your code became Spaghetti Code. Everyone knows what Spaghetti Code is. It has been said that with objects you get Ravioli Code: 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 Ravioli Code... 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 Ravioli Code 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.

Ravioli Code threatens to bite: this style maximizes maintainability by old hands at the expense of comprehensibility by newcomers. The "Hire Off The Rack, 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 System Metaphor(s), Patterns and other explicit descriptions of architecture come in. Ravioli is only unmanageable when there's no way to see its symmetries and Common Sense.


There are a few reasons I believe you do not get Ravioli Code when using XP. I'm sure there are more so I will encourage others to add their arguments as well.

Pair Programming - It might be more true if you were to go at a new system by yourself, but with XP you always tackle a problem with a partner who is there to help keep you sane and think about the overall effect of the changes you are going to make.

Refactor Mercilessly - The refactoring mentioned above is only part of the refactoring that happens. Not only do you create new simple classes and pull out some code, there is also the consolidation of multiple classes, which were once dispersed, but can now be brought together in a much more cohesive and understandable set (removing the ravioli-ishness).

Smalltalk Best Practice Patterns - Here I'm referring to especially the ones dealing with using appropriate naming conventions for classes, methods, instance variables, etc. Using consistent naming allows the developer to understand the purpose and responsibilities of the entities involved in the change.

BTW, Ravioli Code has also been referred to in the Anti Patterns Book (I didn't find this one on Wiki) as the Poltergeists Anti Pattern. The suggestions for fixing this problem all stem from multiple levels of refactoring. - Tom Kubit


Although it often does, I don't think Ravioli Code 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. -- Stan Silver


You Arent Gonna Need It helps avoid unnecessary ravioli. Ravioli comes from making fine distinctions, and we often see distinctions which aren't really relevant yet. Once And Only Once 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? -- Dave Harris


Yes. I'm tending to think that Ravioli Code 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. -- Greg Vaughn


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 Ravioli Code. 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 Ravioli Code, just appropriately factored code. So I think we're agreeing here; its just a matter of the definition of what we were thinking Ravioli Code really meant. -- Tom Kubit


See Reading Ravioli for a suggestion that effective reading of Ravioli Code 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 Lasagna Code? :)

I thought that Lasagna Code was a synonym for Alternate Hard And Soft Layers...


If you have a nearby CS library, look up Guy Steele'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 Big Ball Of Mud www.devcentre.org !


I love Ravioli Code. 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.

Well, yes, me too, often, when I'm contracting, and need to do a small change quickly. However, there are other times when one needs to understand all of the code as a system (e.g. to prepare for rewriting it because it is foundationally flawed), and in those cases, Ravioli Code actively hinders that understanding.

A good source browser (one with a single keystroke for "take me to the source of this method") and a good debugger make managing Ravioli Code easy.



My pain with Ravioli Code 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 Tips For Reading Code and Reading Ravioli.

I don't see how ravioli code makes it harder to apply Tips For Reading Code.


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 Ravioli Ware 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

bloat

lack of determinism & poor latency

poor performance.

- Paul


Ravioli Code can be caused by disguised Global Methods. 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 Code Smell ... I just need a snappy name for it. Stateless Object, 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 Ravioli Code is a Unified Data Model. -- Mark Janssen

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 Pasta Code.


See original on c2.com