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

> You can get pretty far with good abstractions and dependency injection

Which goes back to the article's point of having to write code that is unit test friendly.

Now architecture decisions have to integrate interfaces that wouldn't be needed otherwise.

> Maybe you could elaborate. I really don't understand what you mean here.

Modules keep state via global variables, module private functions and the surface control that they might expose via public API for the module.

Additionally on languages that support them, they can be made available as binary only libraries.




> Which goes back to the article's point of having to write code that is unit test friendly.

> Now architecture decisions have to integrate interfaces that wouldn't be needed otherwise.

You're not wrong.

But in the context of functions, that doesn't seem to me to be particularly onerous. If the worst I'm forced to do is change the type of my parameters to an interface instead of a concrete type, that seems like a pretty small price to pay for easy testability. Certainly a much smaller price than the examples in the article.


You are assuming that interfaces exist as language concept.

Imagine doing unit tests for a C application, where modules == translation unit/static/dynamic library, thus you can only do black box testing.

Now one needs to clutter it with function pointers everywhere, or start faking interfaces with structs, just for the benefit of unit tests.

And with static/dynamic libraries than one might need to start injecting symbols into the linker to redirect calls into mocking functions.

All just to keep QA dashboards green.


That's how a lot of great C code is written anyway. A C library should abstract out logging, allocation, and IO so that the client code can change them out if need be.

The fact that it makes unit testing easier is just icing on the cake.


Having written tests for enterprise C code, I wouldn't call it a great experience, rather something I am glad not to ever repeat again.

Mainly due to the linking hacks and low level debugging sessions required to mock all necessary calls.

Plus that was just an example, there are plenty of languages with modules and binary libraries.


I mean, that's why great libraries don't make you do that. There's a lot of crap libraries.

The libraries dependencies should all be indirected through whatever context struct you pass to all your calls.


Agreed, and this goes back to the initial thread that just because a language is more focused on functions it doesn't make testing automatically better, unless it was written with testing friendliness as part of the requirements.

Sadly not all code is great.


For C, I've found it's not a test friendliness thing though; the great C libraries were doing this before unit testing made it's way into their codebases. They dependency inject IO, memory allocation, and logging because they have no idea what you as the end user are going to be using for those. So you pass all that in on an env struct when you initialize the library.

You probably want it rigged up to your own logger instead of just blindly writing to stdout. You probably want the library's allocations tagged somehow on the heap so you can track down memory leaks. You probably don't want it doing IO directly, because of how many different way there are to do IO.

It's all more a function of how incredibly varied c envs are, than design for testability. It just happens to be very testable as an aside.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: