Hacker News new | past | comments | ask | show | jobs | submit login

Move most of your code to pure functions, that is the number one mantra to solve most scaling problems in software development. Even in an OOP paradigm, it makes sense to make almost all objects as purely functional, with limited use of internal state.

The second mantra is to think a thousand times before you name something. I actually keep a list of names (..Manager, ..aggregator,etc.) gleaned from various sources, to name my classes. Earlier, I used to name most of my classes as <Function/Operation>Manager

Edit : Here is a question, that actually prompted me to keep a list.

https://stackoverflow.com/questions/1866794/naming-classes-h...




> (..Manager, ..aggregator,etc.)

Names ending in Manager are usually a poor choice.

See Peter Coad's "-er-er" principle:

> The “-er-er” principle. Challenge any class name that ends in “-er.” If it has no parts, change the name of the class to what each object is managing. If it has parts, put as much work in the parts that the parts know enough to do themselves.

See also: http://www.carlopescio.com/2011/04/your-coding-conventions-a...


I think the commenter generally views things as code acting on entities. If so, that code is suited to being called an xxxManager, or xxxService, or xxxCoordinator, or xxxController. Of course we have returned to a place in history by doing so, of creating big balls of mud as complexity increases.

Peter Coad advocated against this in favor of modeling the problem domain under consideration using an object oriented approach.

In an object oriented domain model there is no place for such external “controllers”, but I think the commenter doesn’t propose this approach.


I have an object called TransportMaster, with concrete implementations X_TransportMaster, Y_TransportMaster, Z_TransportMaster. The application instance may contain any number of any mixture of these objects, and they may be created and destroyed at any time by the user. Their use within the application is also subject to the user's whims.

Why would a TransportMasterManager, which provides factory methods, enumerations, a collection of the current set of TM's, and knowledge of the current user choice for which TM's is being used for what, have "no place" in this design?


>modeling the problem domain under consideration using an object oriented approach

Really curious. Do you have any material that explains this way of design?

I work on mostly web apps. End of the day, it's really about moving data and transforming data. So most of my programs have no choice but to deal with data, and so, my whole design process revolves around gathering, storing, operating upon and transferring data.


I don't know Peter Coad, but the approach reminds me of domain driven design (DDD). Most business logic would be in objects named entities, but DDD has also services, since there might be logic that affects multiple entities (actually special entities called "aggregate root").


Peter Coad did write a number of books, which are pretty old and likely out of print. How to actually model a complex system into an object oriented domain model, is something I have long thought to teach. However, sadly there seems little appetite in a world currently dominated by procedural code acting on data, modeled using functional decomposition or through a relational data model. Of course our industry will eventually relearn the forgotten lessons and methods of the past, rename them as something new, and adopt them as the new silver bullet for software development.


Perhaps you can explain this part from the post you linked which is perplexing me:

> AppDomainAffine, therefore, would be a more appropriate name. Unusual perhaps, but that's because of the common drift toward the mechanics of things and away from concepts (because the mechanics are usually much easier to get for techies)

how is 'AppDomainAffine' not a concept?


I read that as saying that AppDomainAffine is a concept, and that's why it's an unusual name, because a lot of naming these days focuses on mechanics instead of concepts (c.f. MarshalByRefObject)


ah okay that makes sense I was thinking it was opposite of that which made no sense


One of my favorite classes in my code base is called something FooBarBazListenerListener


> think a thousand times before you name something

I gave up .... I write mostly in languages that allow you to deterministically rename things with refactoring tools, so I frequently rename important classes 5 or 6 times before I'm done.


Completely agree. I find that the right name takes ages to come about. Worse, it may require a lot of architectural refactoring that, many times, has nothing to do with the one entity you are trying to name. Instead, it is connected with the entire workflow you are designing. Nothing worse than spending ages coming up with the right name for a class, only to find out the entire class is not needed and you got the workflow all wrong :-) which I have done many a time, to be fair


This.

Not only renaming, but re-bundling entities, moving layers, changing abstractions – refactoring is crucial during and immediately after development. As you implement your idea, you will inevitably find a better way to express it, and it's crucial to be able to re-do these things as many times as possible to reach the best possible result (if it's not a throwaway prototype, of course): no maintainer, including yourself a month later, will have a picture as full and clear as you right after finishing the first iteration.


I've been around long enough to remember a time before refactor->rename was a thing. Now naming can evolve as the class/variable evolves so there's so much less initial cognitive overhead worrying about a name than there once was.


Likes more like a list of names to avoid for me. Manager, handler, controller, and service add little to no information. I try to find more specific verbs instead.

Distributor is a better one sometimes. For example, ConnectionDistributor instead of ConnectionManager if it accepts connections and distributes them to a thread pool.



The thing is a proper REST API is a Kingdom of Nouns. The core issue is that very few were doing object oriented programming and design the way it was intended. Giving me some leeway here, Kay's original idea was a programming model similar to that of the internet but in memory.

If one's position is that striving for a distributed model in memory is the wrong approach because of the inherent complexity associated with distributed systems that's fine but I rarely hear this argument. Typically, OOP/OOD is criticized based off of patterns that aren't proper.


Agree on the functional bit.

Naming things: I try to not think about it for more than 10 seconds, and go with the best I've got by then. I find myself renaming things sometimes, and I'm eager to do this when a better name comes to me.


I use the thesaurus that comes with macOS whenever I think of a name and it just doesn't feel right. Then I typically find a more fitting name after spending 20 seconds looking at near synonyms.


I did try that. That is how I ended up with 50 "Manager" classes in my app.

At that point, it is a cognitive burden to handle so many "managers".


Shakespeare the software architect: "First kill all the Managers".


Before we shuffle off this mortal stack.


Yes this. Naming is an intuitive thing, you can't force it, and it will get in the way, moreover, it's fluid and won't matter until later, things could change.

Just name it whatever and come back to it when it starts to matter more and you've probably thought of something better by then.


Renaming things is a luxury only enjoyed by people who don't have other people using their code downstream. Once people have used it, renaming things becomes a breaking change others in your organization will oppose.


Or hopefully your code reviewer suggests names that are better if your choice doesn't make sense


That is true. I am also the code reviewer at this time, but I do perform code reviews.


Pure functions can also easily be memoized which can speed up processing.


Another pet peeve of mine is variable names suffixed with "Data" and "Info".


Yes, but... sometimes you have data about data (aka metadata) or about a thing, in which case "...Info" is the best thing I know of. Say FileInfo or ProgramInfo (e.g. a CNC machine program).


Worst variable name I’ve ever seen was “data2”. There was no longer a “data” in that code but presumably there had been at one point.


Kill "Manager" of that list :). Adds to the naming burden (aka quality) by removing the fallback :).

I will adopt the list idea!!!


It's an old talk but it zero's in on a point that is tremendously over looked in discussions about OOP/OOD.

https://www.infoq.com/presentations/Making-Roles-Explicit-Ud...


Pure functions are a good solution for a onion in a request / response pattern (which a lot of the scenarios are). However, an onion architecture representing something with state (e.g. a shadow Dom implementation), sometimes a OO inner core is the right solution.


Would love to see your list of names if you’re willing to share!



It's not just pure functions. Two things break modularity: Free variables and mutation.

The problem with OOP is that no method is truly pure, no method is a combinator.

   class Thing
      var memberVar
      def addOne():
          return memberVar+1;

The above is an example of your typical class. AddOne is not modular because it cannot be used outside of the context of Thing.

You can use static functions but the static keyword defeats the purpose of a class and makes the class equivalent to a namespace containing functions.

   class Thing
      static def add(x):
           return x + 1;
the above is pointless. Just do the below:

   namespace Thing:
       def add(x):
           return x + 1; 
The point of OOP is for methods to operate on internal state. If you remove this feature from OOP you're left with something that is identical to namespaces and functions.

Use namespaces and functions when all you have are pure functions and use classes when you need internal state... there is literally no point for OOP if you aren't using internal state with your classes.


Scaling is not the only way to accomplish high-performance. In many cases performance can be achieved with stateful, imperative yet efficiently executed code that economizes on the use of resources on a single node. In many cases, such as for mobile, desktop, or on-prem deployments, this is the only way to "scale" since you do not have the luxury of increasing number of nodes on demand.


I think the parent comment is talking about scaling in terms of software size, not performance.


I meant scaling of software development. As in, how to make sense of large amounts of code.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: