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

I’d be very wary of hiring an ”OO” dev who can’t reasonably formulate what the SOLID principles are and why they exist.



SOLID is mostly a bunch of over-confidently stated opinions.

Here is my over-confidently stated opinion: if a principle is not applicable to Smalltalk 74, it is not essential to OOP.

The only rule in SOLID I would say someone should follow at all times is L, and even then only in statically typed languages.

This should be obvious. For example, can you define "responsibility" in any way that's not entirely gut feeling? No. So how can you fault someone not knowing about a rule that's based on gut feeling?


It's not really gut feeling. The following is very abstract but it's how I think about the "single-responsibility principle."

When you're designing a software system you need to step back from the individual components for a moment and consider the overall system -- who is using this system, what is the problem being solved here, and how does this solution relate to other problems and solutions within the system. It's not obvious only if you don't completely understand the problem domain, which most people don't.

If you find yourself thinking that some object's responsibility is ill-defined, you need to talk to whomever authored that part of the code to see if there's something you're missing about the system that the code controls. Either you are or they are, and at any rate the conversation will make the software system better somehow, which is the goal.

So once you understand the system and you understand the problem that you're trying to solve, and you think you have a solution, it's an exercise for you to sit down and identify specific activities that the software system has to undertake in order to solve the problem within the context of the system. You can consider these "responsibilities" at a top level and start partitioning them up further into classes that mutate and emit data in response to data received from other components of the system. The boundaries of these classes are interfaces, and each interface should be responsible for operating on a specific kind of data in response to its inputs.

Now the interface itself also needs to be defined in terms of the problem the class is solving. So you use words like "setMotorSpeed" on a class called "ConstantSpeedServo," and your ConstantSpeedServo might be composed with a "ValveController" which is responsible for controlling the position of a valve based on some input data.

This all goes back to thoroughly understanding the system you are controlling so that you can write code in terms of that system, but it goes beyond that in that you have to be very explicit in your understanding of what it is the system does in order to write software that accomplishes that goal.


They’re guidelines and tools. You have to know how and when to use them. There are no unambigous rules in programming beyond what the language itself enforces. But that doesn’t mean some rules aren’t useful. As the saying goes in science: all models are wrong but some of them are useful. Or in art: you have to know the rules before you can break them.


Even Solid, like OOP is one of those concepts that has morphed more into an ideology than it needs to be with blind faith adherents

https://speakerdeck.com/tastapod/why-every-element-of-solid-...

I'll take someone who writes simple code that can be easily changed 101 out of 100 times over a SOLID, OOP Adherent.


That presentation basically says "write simple code". I'm not sure how is that helpful to anyone.


It's immensely helpful.

Stuck in a rut designing your type hierarchies and making sure they are perfectly SOLID? STOP. Write the simplest, most clear and concise thing that works, refactor it once it gets too big to fit in your head.

Not sure if your AbstractFactoryBeanProxyImplImpl is generic enough to cover all use cases? STOP. Write the simplest most clear and concise thing that works, refactor it to adapt to more problems as needed.

Tired of fighting your type system because your stuck in a wheel of is-ha has-a is-a has-a? STOP. If it acts like a duck, and quacks like a duck, it is a duck! Write a duck!


I'm by no means advocating SOLID is the right/only way. I agree with "Write the simplest, most clear and concise thing that works", but it offers no help on how to do that. The how comes from experience. Simplifying complex and large things takes effort and thinking. SOLID helps with that, if used right and not as a religion. I feel "do the simplest" is way too generic an advice.


"You Aren't Going To Need It" is the most overlooked piece of advice anyone has ever given anyone.


I'd be wary of companies hiring "OO" devs.


Depends on what this dev would be building, if you have to build framework or you build a library then I agree. If you build next off the mill "business" system then...

Single responsibility principle, yes nice but we have deadlines and no time to argue if that one function should be somewhere else, fix it when we have some slack.

Open closed principle, you don't have to think about if you use DI and have interfaces.

Liskov substitution is useless, you should not use inheritance but composition.

Interface segregation, you have to think about it but it is a lot like SRP.

Dependency inversion, interfaces plus DI framework takes you far enough.

So IMO if one senior guy sets up project with DI framework and gives general direction, someone who can't formulate SOLID still can be good OOP developer.


> Liskov substitution is useless, you should not use inheritance but composition.

Liskov substitution is more about interface inheritance than implementation inheritance, really. LSP basically says that the implementer of an interface must obey the contract the interface specifies. As a real-world example, throwing UnsupportedOperationException in a method implementation is an LSP violation. Of course, this makes it vital to get the interfaces themselves right, carving the solution space at its joints.


Ok yes, it is about subtypes and interface is quite of an abstract base class. But if you have interface as in Java or C# and maybe 2 or 3 implementations without complicated type hierarchy under it, it is not an issue in practice to be not strict about contract, because you can spot deviation from it and fix it quick (ideally you also have integration tests to spot it for you).


I think the point is to forget about specific language features for a moment and think about interfaces the same way a mechanical or electrical engineer does -- as things to be glued together.


No, Liskov substitution is much more abstract level, if you go with physical interface definition it does not work at all. It is not about attaching things but about type hierarchy. Thing you describe does not account for Covariance and Contrvariance and then it also goes into generic types which also huge abstraction which does not fit in physical world.


Do they have to agree with them, or just be able to name them?


Well, it's definitely a plus if they can convincingly argue against any of them. They're tools, not dogma.




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

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

Search: