, the following was said:
The most cheapest
time to detect type bugs is when writing the code.
I disagree. Is your compiler really that slow or your environment really that cumbersome? Let the compiler do what the compiler is better at.
Here's the on-going discussion moved from there...
[It takes 30 minutes to compile some systems at work on a dedicated PII 300 with 256MB of RAM. 10 minutes to compile one project. I have found it is sometimes necessary to recompile large portions of projects, especially if I modify an elemental class, only to have to recompile when I make a type mismatch. This does not happen frequently using HungarianNotation.
Also, it is cheaper to detect the bug while writing the code whilst PairProgramming, or in groups, or code reviewing, because compiling can waste many people's time - causing frustration.
Besides, it's easier to stay with the MentalStateCalledFlow if you don't have to take timeouts while compiling in the middle of your work.
Speaking of which, I find it disruptive to have to look at the declaration of a variable when all I want to do is write the algorithm I have in my head and move on. It breaks my thought patterns unnecessarily.
And when maintaining UndocumentedTrickyCode it is a godsend because I don't have to hunt for the declaration to understand what the heck is going on. This one I know from hard won experience. It's always a good idea to CodeForTheMaintainer, which is where HungarianNotation really excels.
You win... your environment really is that cumbersome. It seems reasonable to me to do whatever part of the compiler's job you can do better, although it galls me that people have to work in such bad environments - I'd be banging at the bars of that cage. This reminds me of the MainFrame
batch days, when you'd check your code a dozen times before submitting it, because your next run would not be any time soon. -- WayneConrad
[Wasn't trying to "win" like that. ;)
We had a hideous CeePlusPlus
project at one place I worked. Part of the problem was that the make files only barely even build the code much less checked for dependencies. We'd end up having to run the make several times so that libraries would be compiled but the things that depended on those libraries and tried to build first failed. They'd compile on the second iteration. The last iteration would catch any stragglers. We all knew there was a problem with the Makefiles but no-one was ever willing to try to devote time to fix them. (That'd get us in trouble with management due to other deadlines slipping.) I left that job pretty quickly.
I find that Make itself tends to be awkward and I keep telling myself that there's got to be something better out there. I have yet to find anything though. -- BruceIde
It's not a bad environment because the project is poorly written (well, I wrote large sections of it, so it had better be well written!). It is a bad environment because there is no acceptable environment for the project. CeePlusPlus is a StronglyTyped language. SmalltalkLanguage isn't. We use C++, not Smalltalk, because we're writing applications for the RealWorld... well, at least SoftRealTime? systems, which don't work well in Smalltalk.
These kinds of problems are becoming more and more prevalent again with ObjectOrientedProgramming. The more I use OOP, the more I'm noticing a general downward trend in life. UnifiedModelingLanguage vs FlowCharts, multithreaded bugs vs pointer bugs. Long compile times vs long compile times. I'd never go back to StructuredProgramming, but I'm not eating ambrosia here.
Software is always more complicated than the tools we have to write it with.
Or, similarly, just as soon as we begin to understand how to write software, 'omeone pulls the carpet out from under us.
A MooresLaw of complexity?
Well, I guess I was picking on CeePlusPlus
. I've lived through the change-one-class-and-recompile-everything bit, and it's not fun. Templates make things even worse. What strategies have you used to try to keep the compile times down?
My strategy is to simply use DelphiLanguage. Recompile whenever you change a letter, it'll just take a sec or two.
I've never written a large project in JavaLanguage
, so I don't know how badly it suffers from this problem. My Java programs are much smaller than the equivalent C++ programs, however.
Getting back to HungarianNotation
, I never felt a need for it even when working on gargantuan systems with long compile times. With a good set of make files, the stuff you've already compiled will be skipped, so it's relatively painless to make, fix some syntax errors, and then make again.
I have the feeling that Hungarian is a "what's good for me isn't good for you, and what's good for you isn't good for me" issue.
[Mostly I stick to the UseForwardDeclarations idiom (combined with IncludeOnlyWhatYouNeed?, HidingHeaders?), PrecompiledHeaders?, IncrementalLinking?, good make files, build scripts, distribution of the project into libraries, include libraries in libraries, minimizing template use, and more that I can't think of right now.
Actually, at work, I have two development machines. One is my primary machine which has my complete environment on it with all my tools. I do major work on this machine. The other machine has the necessary hardware to test with. I do all serious debugging on that machine. When I'm working on one machine, I do a full build on the other.
I also tend to only compile the current module I'm working on while hammering out syntax errors and then attempt a project-wide, then system-wide build.
If I have to wait, I get a Coke(tm) and walk around, socialize, throw darts, think, eat lunch, whatever. Waste time.
One of the big problems of using many libraries with templates and elemental classes is that you end up having to recompile a massive number of projects in order to get a working binary. And link errors only show up at the last possible moment.
HungarianNotation really doesn't help with many of these issues. Only if you are changing code in header files like declarations, function signatures, member variables, inline functions, or (sadly) templates.
HungarianNotation's chief saving grace is avoiding the look-up of a variable during maintenance. (Obviously I know the type of a variable I just created 30 seconds ago! Three months ago? Not likely...) Aside from that it nears worthlessness, I agree.
You're right. HungarianNotation is more of a tool that is used depending on the situation, not a dogma to be followed unwittingly. I certainly don't use it when I write SmalltalkLanguage code, although I experimented with it once. Ugh! E.g., I wrote a compiler in Smalltalk once, which is a fairly complex task, but it was better not to name mangle. Although I do hate the variablesLikeThis style that it forces and that has bled into languages like JavaLanguage. That's another WikiPage... ;)
P.S. We all know SmalltalkLanguage where I work. However, our targeted platform is WindowsNt, not Smalltalk. All InterpretedLanguages from GwBasic to Smalltalk to JavaLanguage are their own platforms. They are not our platform of choice. Interpreted languages are easier to program in. CeePlusPlus is not. We chose C++ because we have no other real choice. It's not a terrible choice, but HungarianNotation simplifies its use. At least in our circumstances.
s and EmacsEditor
(Which arguably is an IDE) will show you the variable name fairly quickly. EMACS has a happy little add-on program called Etags (ViEditor
's equivalent is ctags) that does indexes CeeLanguage
code for you. I've also found Cscope to be an absolute lifesaver when doing code analysis on a lot of C code. I have to wonder if using such a tool to do the job wouldn't be better than cluttering my code with something that many wiser programmers than I here have defined as a CodeSmell
. -- BruceIde
[HungarianNotation's chief saving grace is avoiding the look-up of a variable during maintenance. (Obviously I know the type of a variable I just created 30 seconds ago! Three months ago? Not likely...) Aside from that it nears worthlessness, I agree. -- SunirShah]
Hungarian does make your life easier when maintaining your code, but it doesn't necessarily make everyone else's life easier. Hungarian only makes easier the life of a maintenance programmer who happens to understand the dialect of Hungarian you are using. For the rest of us, it's one more language we have to learn before we can maintain your code. I find it much easier to look up the declaration.
My other objection to Hungarian is that it is a comment that is repeated every time the variable is used. This violates OnceAndOnlyOnce
in a big way. If the type of the variable changes, I have to change all of the comments. If where the variable is (global, local, class-level, static) changes, I have to change all of the comments. Moving a variable is a common refactoring, and I fear that Hungarian makes that refactoring too expensive. -- WayneConrad
[Refactoring is maintaining the code in a much bigger way. Anything to make maintenance easier is a good thing.
I don't know about you, but the types of variables I decorate with HungarianNotation are almost always primitive types. Primitive types don't change frequently. I just don't buy the argument that it slows you down. If it does, I can quickly do a global search and replace. Get better tools. (Even KentBeck is always going on about how he has better tools to help him with ExtremeProgramming! A RefactoringBrowser for CeePlusPlus could handle this kind of thing easily, I'd bet.)
When I was forced to maintain code with no decoration, I was completely lost. I had to hunt around the code for the declaration, which was less useful than fixing the one line and moving on to the next bug.
Maintenance programmers don't care about your declarations. They only care about taking down a bug list. No-one has the time or inclination to learn large parts of the system just to change it. This is especially true in an undocumented, heavily refactored environment where the whole codebase could change in a month.
This is what partially what I meant when I created FractalComprehension. Maintenance programmers need to have a solid understanding of the code they do touch without a wider context.
, but is the environment so cumbersome that it doesn't have some kind of browser where you can right-click on any variable and have the environment take you to the declaration?
I think the point you are missing about SunirShah
's discussion is the he doesn't want to move his eyes or mind from the task at hand, which is writing his algorithm or reading one. Clicking on any variable having the environment pop up a new window counts as a major distraction, a shift of focus.
It has nothing to do with the environment being cumbersome. Any shift of focus causes a loss of thought. Sunir is working to keep his thoughts as focussed and directed as possible. -- AlistairCockburn
Exactly. Thank you, Alistair.
While my enviroment even allows moving the cursor over a variable to get its type via a tool tip, it's a pain in the butt. I have had to spend half an hour tracking down type information for particularly badly written hunks of code many times - which is where all the bugs are, naturally. As I read the code, I reformat it with HungarianNotation
because I'm particularly stupid and can't keep more than five facts in my head at once. Juggling types in my brain is not helpful when I have to sit down to the greater task of rewriting the spaghetti.
So you mean bad code
needs Hungarian? Presumably this doesn't apply to those of us striving to write good code. -- DaveHarris
I read his append as saying that good code
benefits from it because it makes everything clearer. -- AlistairCockburn
While I suppose I didn't write that explicitly, that is also true. Thanks again! -- SunirShah
If it made everything clearer, there wouldn't be an argument. It is a bit like comments. Bad code needs more comments than good code. Strive for code that needs neither comment nor HN. -- DaveHarris
What I don't understand is how this type information is getting used and why it's so critical. I find that I can generally tell everything I need to know about a variable from its name and the way it's used. The exceptions I can think of are scope, because you can't tell how visible your change might be, and strings, because there are so darned many flavors of strings in CeePlusPlus
. These taken together don't justify the use of HungarianNotation
in my mind. Are there others? -- PhilGoodwin
The problem is that a variable has a vector of properties == <name, type, scope, protection level, size, address, ...?> and a variable name is only a one-dimensional (scalar) projection of this vector into the code. However, I would like to know much of this information in-context while I'm reading the code (I placed the properties in descending order of importance). HungarianNotation
projects the first three onto one dimension by serializing them. Other SystemOfNames
still manage to squish the name and the scope together through appropriate capitalization. If you want to seriously get rid of this, you'll need code that is presented in more than dimensions like visual languages, I suppose. -- SunirShah
The thing is that I don't generally want to know any of those things. What I want to know is the variables role in the code and the interface through which I can manipulate it. The role should be identified by its name and the way its being used when I first run across it almost always reveals what I need to know about its interface. But, I think that there is a deeper current to all of this. I think that we work in very different ways. For instance I wouldn't presume to touch a line of code without understanding quite a bit about the design that it implements. I usually look at the variable definitions of a class before I look at it's method declarations and I look at all of the method declarations before I look at the method bodies. So by the time I'm actually reading executable code I have a pretty good idea of what I'm working with. You seem to be able to jump right into the middle of the code and gather the information you need in order to understand it as you go. If that's the case it's no wonder that you value the signposts that HungarianNotation
leaves on every variable usage. They allow you to navigate from the detailed information that is of immediate interest to you to the more general information about its relationship with the system as a whole. Perhaps you can understand why those same signposts might seem to be an impediment to those of us who, having gained a broad understanding of the system as a whole, are proceeding toward and understanding of some particular part of it. I think that you like Hungarian because it delivers information to you just as it's becoming interesting to you and I dislike it because it continuously broadcasts information to me that I've long since lost interest in. -- PhilGoodwin
Well, I never jump right into the code and start typing. That is insanely dangerous. However, I don't waste time by learning more than I need to identify the defect, fix it and verify the changes. However, I appreciate anything that reduces the scope of what I need to learn. There is a limit to how much information I can coalesce in my given timeframe to ensure I'm not creating more defects. So, CodeForTheMaintainer
! They simply do not care about how many DesignPatterns
you used because it's too much information. They start with a problem and work outwards from there, reading documentation as they need it.
On the other hand, on my active project, I am a developer and have memorized 45000 lines of code. At work, more context is in my head than anywhere but the code itself; when asked by a coworker about an issue related to code I wrote months ago, I am capable of correctly identifying the file, method and usually the code block where the problem is. When I leave in a month to go back to school, they are likely going to put a replacement on the project who will not be given time to become one with the code, so to speak. They will start with features to add or something like that and work outwards from there. So I, as a consummate professional, CodeForTheMaintainer
My point is, I'd rather have information I already know rebroadcast to me in order to lower the defect rate.
Moreover, this ExtremeProgramming
business is just too freaking slow. The RealWorld
has deadlines that move faster than three-week cycles (or so management has told me). I will not appreciate revisiting code I haven't seen in four weeks, thousands of lines of code later, if I am once again trying to figure out whether the pixel buffer is in BYTES or DWORDs.
-- Sunir "No bugs" Shah who has been on Wiki way too much waiting for bugs to fix during Beta. ;)
The problem is that a variable has a vector of properties == <name, type, scope, protection level, size, address, ...?> and a variable name is only a one-dimensional (scalar) projection of this vector into the code. However, I would like to know much of this information in-context while I'm reading the code
While walking home, I realized that all my yabbering about SelfDocumentingCode
is related to this compressing as much information into the code itself as easily as possible. The reason being, I guess, is that when you're solving a problem, you typically want as much information as you need right at hand, but no more than you need lest you get confused.
I will freely admit that HungarianNotation
isn't easy, or elegant, and downright ugly. It just seems to work, in my limited experience, so I like it. If I could supplant it, I would.
So getting back OnTopic
to the title of this WikiPage
, all this crap could be avoided if we weren't DealingWithCumbersomeEnvironments
. The environment being PlainText
. It doesn't have enough dimensions to properly represent the information as we need it.
I once had a SchemeLanguage
implementation that would draw lines from declarations to usages if you asked it to. That was cool. No HN needed there. Tooltips alleviate the problem to some degree as well, as well as jumping to the declaration from the context menu. But they're still too obtrusive...
Thoughts for improvements? We're talking mostly about CeeLanguage
here, I suppose, so the ideas have to be practical.
There's always LargeScaleCppSoftwareDesign by JohnLakos - ISBN 0201633620
Or small classes and small methods, that way the declarations are always nearby. Also, use more encapsulation. I shouldn't care whether the pixel buffer is implemented in DWORDS or not. If its interface doesn't take what I have I'll find out at compile time and change it. Type problems are best solved, by and large, by choosing not to have them in the first place (that is: if your problem is that you have one type and need another, fix the code so that it accepts either type, that way you won't have the problem again). -- PhilGoodwin
The interface to the pixel buffer code is relatively typeless. It takes an AbstractBaseClass
pointer in most cases. However, the implementation that manipulates the internal buffer needs to know the primitive types. Typically, there are very few interfaces
that need HungarianNotation
(because you'll look up the full signature anyway), but implementations
do, in my experience. Perhaps this is only important when you deal with low-level calculations... hmm... -- SunirShah
It seems the editor should be the place to resolve the HungarianNotation
issue debated here. The editor I use (Source Insight, http://www.sourcedyn.com/
, no affiliation) allows code to be displayed with Syntax Decorations. These decorations are generated for display purposes only and are never stored in the file buffer at all. You can pick and choose which decorations you want enabled. Decorations may modify color, font size, font style. Syntactical elements can be replaced with non-standard, but more intuitive symbols.
For instance, a CeeCeePlusPlus
== is displayed with a long single equal sign, while a = is displayed with a single glyph left-pointing arrow. Similarly, a -> is a single glyph right-pointing arrow. !=, <=, &&, ||, /, can be displayed as you'd see them in a math book. Close braces can be displayed with a display-only gray pseudo comment that describes the block being closed base on the code that opened the block.
Since Source Insight has a symbol database, it knows the definition of each variable and with a relatively simple enhancement, could generate (for display purposes only), the Hungarian variable name prefix in front of each variable. Only those that want to see it, would see it, when they want to see it. If I'm writing brand new code, I turn it off. If I'm dealing with old code and it helps me, I turn it on. The actual code follows the OnceAndOnlyOnce
The Hungarian prefix would be a different color from the actual variable name and could not be overtyped or deleted, (likely gray to indicate that it is not really code).
You could even extend the idea to allow some people to see variable names likeThis, or like_this, but that might get confusing. -- JohnVriezen
Hmm I like the sound of this. Anyone know of an EmacsEditor
mode that does similar? If not, I may have to have a go at writing it. Glasses mode seems like a good starting place (it displays someWordsBangedTogether as some_Words_Banged_Together without actually altering the name in the file).
The simple fact is we have the capability of addressing all of these needs but no-one is implementing it. Imagine how much more productive it would be in this environment:
- In RealTime, as the code is edited, it is compiled in an offloaded CPU/Disk, thus with 0 performance overhead.
- An ability to tag a variable as 'Any' for now, just to 'get on with it and write the algorithm'. It can only execute in debug mode (you can't release code with Any's), but it does run and the compiler does infer the type as best as it, substituting/flagging where necessary.
- A change in the use of a type auto-casts it (highlighting it if necessary) without typing.
- An IDE option to hide all casting.
- When hovering over something, your other monitor asynchronously, on a different CPU (no performance overhead), immediately finds and highlights all places and classes in which it is used in one window, and the type and declaration in another. And the intellisense/overloads are displayed tabular (you don't have to scroll through them and they don't overlay on top of code - it's on another monitor ONLY if you need to look there).
- ...millions of other ideas...
C'mon guys, hardware is insanely cheap compared to labor. Implement this stuff.