10 ms·
One of the Best Bits of Programming Advice I ever Got
- praptak 15y agoI was lucky enough to get an equivalent piece of advice from "Object Oriented Programming" by Peter Coad & Jill Nicola ( http://amzn.com/013032616X http://amzn.com/013032616X ) which was the main textbook for an OO course during my CS studies. There are good examples there that illustrate this and many other useful rules (of thumb) of OO modeling.
- latch 15y agoGoogle has posted warning signs to look out for in code (1). One of them is very similar: Suspicious names: context, environment, principal, container, or manager (all of the things google mentions, are things I've seen much, much more in Java codebase than anywhere else) (1) http://googletesting.blogspot.com/2008/11/guide-to-writing-testable-code.html http://googletesting.blogspot.com/2008/11/guide-to-writing-t...
- jwdunne 15y agohttp://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/ http://misko.hevery.com/code-reviewers-guide/flaw-digging-in... This is the full article mentioned above.
- dxbydt 15y ago166 violations, of the 4025 classes/interfaces in java 7: That's 4% of Sun's own JDK, not counting user defined classes. In my 15 years of Java pgmming, I've seen enterprise programmers almost always start out their OO design with a class named "xyzmanager"...probably reflecting their subliminal desire to become a manager someday :) ------ AbstractDocument.AttributeContext AbstractRegionPainter.PaintContext AbstractRegionPainter.PaintContext.CacheMode AccessControlContext AccessibleContext AppletContext BAD_CONTEXT BeanContext BeanContextChild BeanContextChildComponentProxy BeanContextChildSupport BeanContextContainerProxy BeanContextEvent BeanContextMembershipEvent BeanContextMembershipListener BeanContextProxy BeanContextServiceAvailableEvent BeanContextServiceProvider BeanContextServiceProviderBeanInfo BeanContextServiceRevokedEvent BeanContextServiceRevokedListener BeanContextServices BeanContextServicesListener BeanContextServicesSupport BeanContextServicesSupport.BCSSServiceProvider BeanContextSupport BeanContextSupport.BCSIterator CompositeContext Context Context ContextList ContextNotEmptyException ContextualRenderedImageFactory DirContext DOMCryptoContext DOMSignContext DOMValidateContext DragSourceContext DropTargetContext EndpointContext EventContext EventDirContext FontRenderContext GSSContext HttpContext InitialContext InitialContextFactory InitialContextFactoryBuilder InitialDirContext InitialLdapContext InputContext InputMethodContext JAXBContext LdapContext LogicalMessageContext LoginContext MathContext MessageContext MessageContext.Scope NamespaceContext NamingContext NamingContextExt NamingContextExtHelper NamingContextExtHolder NamingContextExtOperations NamingContextExtPOA NamingContextHelper NamingContextHolder NamingContextOperations NamingContextPOA NoContext NoContextHelper NoInitialContextException NotContextException PaintContext RenderContext ScriptContext ServiceContext ServiceContextHelper ServiceContextHolder ServiceContextListHelper ServiceContextListHolder SimpleScriptContext SOAPMessageContext SSLContext SSLContextSpi SSLSessionContext StyleContext SynthContext WebServiceContext XMLCryptoContext XMLSignContext XMLValidateContext _NamingContextExtStub _NamingContextImplBase _NamingContextStub ActivationGroupDesc.CommandEnvironment Environment GraphicsEnvironment GroupPrincipal JMXPrincipal KerberosPrincipal Principal Principal PrincipalHolder ProcessingEnvironment RoundEnvironment UserPrincipal UserPrincipalLookupService UserPrincipalNotFoundException X500Principal AdapterManagerIdHelper BeanContextContainerProxy CertPathTrustManagerParameters Container ContainerAdapter ContainerEvent ContainerListener ContainerOrderFocusTraversalPolicy CookieManager DefaultDesktopManager DefaultFocusManager DefaultKeyboardFocusManager DesktopManager DirectoryManager DomainManager DomainManagerOperations DriverManager ErrorManager FocusManager ForwardingJavaFileManager GSSManager JavaFileManager JavaFileManager.Location JComboBox.KeySelectionManager KeyboardFocusManager KeyManager KeyManagerFactory KeyManagerFactorySpi LayoutManager LayoutManager2 LogManager ManageReferralControl ManagerFactoryParameters MemoryManagerMXBean MenuContainer MenuSelectionManager NamingManager POAManager POAManagerOperations PropertyEditorManager RepaintManager RMISecurityManager RootPaneContainer ScriptEngineManager SecurityManager ServantManager ServantManagerOperations StandardJavaFileManager ToolTipManager TrustManager TrustManagerFactory TrustManagerFactorySpi UIManager UIManager.LookAndFeelInfo UndoManager ---------
- timclark 15y agoI particularly dislike classes called *Helper
- MartinCron 15y agoI'm with you there. Aren't all classes supposed to be helpful?
- Kototama 15y agoEven better: don't use objects at all. Use a functional programming language.
- cousin_it 15y agoObject oriented programming is the sweet spot solution to many problems. For example, if you have a UI with several text fields, it's natural to think of them as objects that have methods like setText(), setEnabled() and such. These methods often have side effects and that's their whole point. Of course functional programming also has use cases for which it is the sweet spot solution, e.g. writing compilers.
- Kototama 15y agoI'm overreacting mainly because these last days I saw code with some Java classes just acting as data holders. It's verbose and obscures the intend. Data deserves much more than being encapsulated in objects, data deserves the right to be put in front of the programmer so that he better sees how ill-designed his data model is :-)
- danieldk 15y agoThese methods often have side effects and that's their whole point. You don't need state and mutations, GUIs can also be programmed nicely using functional reactive programming (FRP). A nice description of FRP: http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming http://stackoverflow.com/questions/1028250/what-is-functiona... Some examples of FRP in GUIs: http://www.haskell.org/haskellwiki/Reactive-banana/Examples http://www.haskell.org/haskellwiki/Reactive-banana/Examples
- cousin_it 15y agoA simple counter that can be manipulated with two buttons "Up" or "Down": https://github.com/HeinrichApfelmus/reactive-banana/blob/master/reactive-banana-wx/src/Counter.hs https://github.com/HeinrichApfelmus/reactive-banana/blob/mas... main = start $ do f <- frame [text := "Counter"] bup <- button f [text := "Up"] bdown <- button f [text := "Down"] output <- staticText f [] set f [layout := margin 10 $ column 5 [widget bup, widget bdown, widget output]] network <- compile $ do eup <- event0 bup command edown <- event0 bdown command let counter :: Discrete Int counter = accumD 0 $ ((+1) <$ eup) `union` (subtract 1 <$ edown) sink output [text :== show <$> counter] actuate network This doesn't look like good UI code to me. It seems to use too many advanced FP concepts that have nothing to do with the task at hand. Are you sure this is better than the OO approach? Why?
- philbarr 15y agoI generally accept the point made in the article, but what should I use in place of "Controller"? If using MVC I generally call it "ApplicationController" or "SimpleController". Should it be "Application", "ApplicationControl"...?
- lallysingh 15y agowhat do the controllers actually do? Synchronize state? Verify that constraints are met?
- dasil003 15y agoI believe the OA's intended question is what are the controllers? Well, what are they? Yes, I know they control things, but what is the actual thing that they are?
- philbarr 15y agoYou're suggesting I call them "StateSynchronizer" or "ConstraintVerifier"?
- lallysingh 15y agoNo, I suggest you name it after what it actually does. "Controller" is a role that's only defined in terms of what it interacts with. It's essentially a declaration of rank with other types; it doesn't say anything about what functionality the class provides. If I'm looking at the components of the software, and I want some code to do X, or wonder what a class Y does, what does "Controller" tell me? If you're doing constraint verification (for example), my preference is to have a container (e.g. vector<>) of Constraint and just run find_if() to see when Constraint::Valid(environment) returns false. Then it's a class called ConstraintVerificationUtil and it has a single static method: VerifyList.
- deleted 15y ago[deleted]
- 15y ago
- ilcavero 15y agogood explanation of procedural vs OO programming, but I got kind of lost with the -er tip, is it all about naming conventions, should I go and rename all my ZzzXxxer classes to XxxxZzz?
- stefs 15y agoyes, that's his advice. Organizer -> Organization, don't ask, just do it. while this sounds silly, i think it's all about getting into the right state of mind.
- DrJokepu 15y agoI disagree with this advice and the reason I disagree with it because it completely disregards the human tendency to name objects (not OOP objects, but real-life objects) based on their functionality. Guess what a photocopier does? Or a scanner? An eraser? An elevator? I don't think these are particularly bad names; quite the contrary, their meaning is very clear. Why would it be any different for OOP objects? If there's an object with an internal state that chiefly responds to messages about scanning things, what's wrong with calling it NSScanner?
- nhebb 15y agoI was going to write basically the same thing. I used to combine data and action in the same classes but recently have begun refactoring them out into separate data and "-er" classes. Maybe somewhere an OOP purist is frowning, but I really prefer this naming convention. My FlowchartShape class included methods for formatting and positioning. I now have a FlowchartShapeFormatter class and a FlowchartShapePositioner class. Guess what they do?
- pgroves 15y agoAgreed. The reason I end up with some '-er' classes is to separate out immutable definitions and the classes that work on the definitions. In your example, by making the FlowchartShape a simple definition class, you can then write that to a file or send it over the network as a snapshot of the state of the -er classes. If the article's advice was taken, you'd end up renaming WebServer to be WebPage, but then would have nothing to name a WebPage. (Maybe WebPageSnapshot?)
- glhaynes 15y agoIt doesn't seem like it'd be any more difficult to write the FlowchartShape to a file or send it across the network if it had additional methods on it to manipulate and use its state, so I'm not sure what's gained by making two+ separate classes... what am I missing?
- 15y ago
- ctdonath 15y agoAmazing how small linguistic changes can cause large semantic shifts. Comparable to the post's rule: in English, a few rules I've picked up are - avoid words ending in "ly" (suffix weakens concepts; suggestion from Stephen King) - never start a sentence with "I" and otherwise minimize its use - "but" negates everything that came before - avoid "to be" Any other such suggestions, in natural or artificial languages?
- ams6110 15y agoAvoid the passive voice.
- r00fus 15y agoThere are reasons to use variants of the passive voice. Using Wikipedia's NPOV [1] approach with speaking with people is very useful in attempting to agree on fact first so emotion is avoided for charged situations/discussions. [1] https://secure.wikimedia.org/wikipedia/en/wiki/Wikipedia:Neutral_point_of_view https://secure.wikimedia.org/wikipedia/en/wiki/Wikipedia:Neu...
- vacri 15y agoScientific reporting also benefits greatly from use of the passive voice.
- ppog 15y agoGeoffrey K Pullum has a delightful article tearing Strunk and White's prescription and examples to pieces. While there's some truth to the advice, it is often simplistically presented and ludicrously overapplied (uh, I mean, "style guides often present it simplistically, and editors often overapply it"). There's plenty of room for the passive voice, and even more so when you consider what Strunk and White consider to be passive even though it isn't. http://chronicle.com/article/50-Years-of-Stupid-Grammar/25497 http://chronicle.com/article/50-Years-of-Stupid-Grammar/2549...
- 15y ago
- mcherm 15y agoI am unconvinced. Any absolute deserves close scrutiny, and "real nouns only" is an absolute. In this case, it fails my test. I find that many things I work with (especially huge Java libraries) tend to have convoluted and difficult-to-understand webs of classes with the most confusing pieces named things like "FooManager" or "FooController". So the author of this piece is reacting to a genuine excess. But Travis is overreacting. The REAL goal is to find a collection of abstractions that is powerful enough to accomplish what the program requires but as simple as possible (and as local as possible) to allow humans to comprehend (and maintain) it. There are quite a few times when I have found that one of these "verb-like" abstractions (a word ending in "-er") made things more comprehensible. For example: the Gang-of-Four patterns "Builder" and "Observer" both end in "-er" and strike me as being well-named. "Builder" is an object with no purpose other than to create (initialize) another object or data structure. HAVING such an object is useful when something requires extensive setup or initialization, because it is easier to understand if the extensive initialization is kept separate from the core functionality. "Observer" is the name for an interface of things that observe... the names of interfaces FREQUENTLY work well as "verbs" since the interface frequently represents "anything that does X". Similarly, I have often had a class such as "DatabaseConnection" and then created "DatabaseConnectionWrapper" -- a class whose purpose is to wrap a DatabaseConnection to do something like logging, error reporting, pool flushing, driver-bug-patching, and so forth. Suggestions that I call these "LoggingDatabaseConnection", "ErrorReportingDatabaseConnection" and so forth misses the key point: a different mix of features may be required at different times (eg: logging in QA but not in Prod); the fact that they are transparent wrappers that can be added (or not) in any order is a key feature of the design. So my own advice would be weaker than Travis'. Instead of "Don't make objects that end with -er.", I would say "Be wary of confusing objects; those ending in -er are often confusing."
- pestaa 15y agoI think there is a more fundamental misunderstanding in OO than bad naming convention. You are right about the usefulness of -er named objects -- but then again, are they really objects, or just functionality wrapped into a wrongly chosen language construct? Following your example, you could have implemented the strategy pattern into DatabaseConnection to freely inject functionality into the object when X happens. Assuming these functions do not have additional data members other than the parent object, they easily can be simple functions or even lambdas. (Of course it's easier to restrict to classes, because you can validate against interfaces in case a function signature doesn't cut it.) What Travis is suggesting, when you have an object that defines both data and behavior, the object context should be determined by the data, not the behavior. If done properly, you end up with less names that end in -er.
- uriel 15y agoThis is interesting in view of Go's convention to use the ending -er for interface types (Reader, Writer, ...) rather than the implementations of those interfaces.
- deleted 15y ago[deleted]
- deleted 15y ago[deleted]
- ubuntufreak 15y ago"What's in a name anyway?" yeah, there's something in a name, it is always good to have a good convention and style in programming But I agree with @Kototama
- dasil003 15y agoWhat do you do if you need a higher level interface to a bunch of classes that are already fairly complex in their own right? Seems to me "plain" nouns (since really these are all nouns) are good for simple concepts and things with real world analogs, but in projects of any complexity you quickly end up with complex logic whose only succinct description is what it does. My experience tells me the key aspect of software quality is the interfaces. The simpler and less leaky the interfaces, the more understandable, maintainable and correct the software will tend to be. Part of this is inherent to the problem itself, but a big chunk of it—especially in the middleware—is the ability of a software architect to have a sense of the whole project and figure out the best places to carve the interfaces. Doing so correctly is the difference between a maintainable million-line project and spaghetti. Truly brilliant engineers will figure out interfaces that make code 100x more reusable and elegant, maybe spawning open source extractions, etc. If something is named well is an orthogonal concern, and highly contingent on what the actual object is. The best code in the world might be impossible to name intuitively if there is no real world analog.
- sethg 15y agoI am upvoting this because I think it is an essay worth thinking about, but I’m not sure if I agree with it.
- mhd 15y agoI really respect the man and his work, but I can't help groaning whenever I read the "I invented the term 'Object Oriented Programming'…" Alan Kay quote. Always struck me as a bit puerile and pedantic.
- 3pt14159 15y agoHaha. Look at the Ruby home page: http://www.ruby-lang.org/en/ http://www.ruby-lang.org/en/
- strictfp 15y agoClbuttic!
- bromagosa 15y agoLots of Smalltalk lately in HackerNews :)
- aangjie 15y agoWell, this is one of my reasons for python over Java as a programming language. There are some procedures that don't fit naturally into a class or object and I should be allowed write functions for them. I was a OOP fan, when i learnt c++, but when i learnt java was put-off by its' requirement of needing a class. I am learning Haskell now, and am a little infatuated with FP, but not sure will enjoy using it a couple of years down the line. I understand the Manager class has some state and methods, but just can't digest the idea of a separate class. To overextend the metaphor, i guess, that's one of the reasons i have shied away in my career from becoming a manager.:-P
- aangjie 15y agoJust curious, why downvote. is anecdotal evidence frowned upon here? Or only opinionated, argumentative positions welcome??
- monochromatic 15y agoRelevant snarky blog post from Steve Yegge: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom...
- tmsh 15y agoThe most correct program (in terms of maintainability and evolution -- as well as mathematical correctness) approximates the most orthogonal program. In term of modeling it with objects that contain state, this may mean having objects that have a varying degree of state (unless you choose other purer approaches). But it's naive to think that all classes should be a noun. Everything should be an abstraction that models the solution. However, nouns that end with 'er' do tend to have a little bit of state that seem unorthogonal. But I guess my point is that that's the wrong way to look at it. Better to think about it in terms of DRY. Some 'manager' or 'controller' classes violate DRY (whereas it's rare for 'connection' classes to). But not all 'manager' or 'controller' classes do.
- SimHacker 15y agoBut I just met 'er!
- 5hoom 15y agoMeh. I'm working on a video game at the moment, and have read lots of advice like this. My old game engine experiments all used 'Entities' to describe objects in the game world, and these 'Entities' were created, deleted and invoked by an 'EntityManager' (kind of half factory & half controller). Every game tick, the EntityManager calls a 'tick' method on all the current game entities and facilitates communication between them. For the most part, all entities are created/destroyed at the same time (game-level loading/unloading). Trying to avoid architecture mistakes, I've come up with all sorts of tortured designs to do away with the concept of any kind of 'manager'. It is probably my inexperience with various design patterns, but all these alternatives were overly complicated and difficult to use. I would end up with a mess of objects & functors all needing pointers to each other & stepping on each others toes. It then occurred to me that my 'manager' was in fact mapped to the real-world concept of 'a manager', being someone/something that is given orders from upper-management (game-level data, user-input, etc.) 'hires' & then assigns tasks to 'workers', hands the results to upper management, then 'fires' the workers when they are not needed ;). The metaphor works. So I'm back to the 'manager' pattern and things are moving ahead quite nicely, even if some OO purists might frown. Should I call my 'EntityManager' 'EntityBoss'? Gets rid of the 'er' at least...
- chipsy 15y agoSimilarly, my game has Managers for entities, collision components, and renderable components. With each one of these, I don't want to try to dump all of the data in one place where the access patterns become strained, I want them to be "managed" from afar, where there's an interface to easily query or update them.
- 5hoom 15y agoYeah, from my own experience the 'manager' metaphor is just easier for understanding the flow of execution & adding-new-features/maintenance. Everything is in one place, and when the systems do need to communicate it is usually in pretty well defined ways (eg. physics manager ticks--> passes collision data to entity manager which ticks--> passes scene data to render manager which draws the screen, etc) I'll go with whatever pattern works best in the name of Just Getting Stuff Done (with my own limited brainpower).