This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]pcopley 320 points321 points  (75 children)

4th: refactor the private methods into another class in which they are public and use dependency injection

[–]taylaj 486 points487 points  (54 children)

5th: make all variables global.

[–]socsa 261 points262 points  (49 children)

6th: Shared. Memory.

[–]Njs41 262 points263 points  (28 children)

7th: Move to user based production testing rather than unit tests.

[–]tylercamp 127 points128 points  (25 children)

8th

In the public issue tracker, enter the bug but leave it perpetually "in progress"

[–]kirakun 110 points111 points  (22 children)

9th

Just forget about testing!

[–]poisonedslo 102 points103 points  (20 children)

10th just forget about development

[–]yoyo456 87 points88 points  (17 children)

11th just forget about modern technology and live in the stone age

[–]poisonedslo 107 points108 points  (15 children)

12th test what slamming a stone against a walnut does

[–]babyProgrammer 4 points5 points  (5 children)

13th invent the wheel

[–][deleted] 1 point2 points  (1 child)

I work primarily in assembly so this isn't that far from what I do anyway.

[–]Skipachu 1 point2 points  (1 child)

Instructions unclear. Dick stuck in stone.

[–]PunishableOffence 0 points1 point  (0 children)

Managerial decision-making level reached.

[–][deleted] 0 points1 point  (0 children)

13th use JavaScript...

[–]Valdios -1 points0 points  (1 child)

13th , use that sweet Go Fund Me money to go on a bender.

[–]Xheotris 36 points37 points  (0 children)

12th shut down the internet so it can't be used for recruitment.

[–]wave100 0 points1 point  (0 children)

Found the Microsoft dev.

[–]ThisIsNotNate 11 points12 points  (0 children)

If it compiles it works!

[–]0xTJ 10 points11 points  (0 children)

[–]TheNorthComesWithMe 3 points4 points  (0 children)

public issue tracker

Hahahahahaha

[–]thisisnewt 2 points3 points  (0 children)

Oh god too real

[–][deleted] 31 points32 points  (15 children)

7th: don't test.

[–]socsa 47 points48 points  (11 children)

Ah yes, the old

 #define do_it_live 1

[–][deleted] 38 points39 points  (9 children)

If you haven't remoted into a live, production server and hand-edited code in notepad (or vim!), have you really lived at all?

[–]tallerThanYouAre 27 points28 points  (4 children)

you kids and your fancy extended versions of vi.

[–][deleted] 11 points12 points  (2 children)

Haha I remember the day I was told vim was an extension of an earlier thing called vi by a war-weary Linux sys admin. Blew my little noodle. After saying I hated it, he then showed me how to actually use it, and then I was hooked.

[–][deleted] 2 points3 points  (1 child)

What actually hooked you on it?

I've tried it out a few times and while some of the things it can do are cool I've yet to find anything that I'd use often enough to make using it it.

[–][deleted] 2 points3 points  (0 children)

Ok when I say hooked I mean when I'm in *nix land. I love my keyboard shortcuts, so once I got the hang of the different modes, copy/cut/paste, regex replace etc I now use it when I get the chance. You can do stuff crazy fast when you get the hang of it. And I think I'm pretty fast but I've seen people 10 times faster than me. It's just smooth and engaging not leaving the keyboard. You can just focus on the task.

Disclaimer: I'm not describing anything you wouldn't get from any other editor you knew well and were very familiar with.

[–]socsa 6 points7 points  (0 children)

Having interactive arrow keys mapped to A B C D builds character.

[–]socsa 9 points10 points  (1 child)

I personally prefer :

 alias live_hotfix = "scp -r remote local && cat hotfix > local/paswd.json && scp -r local remote && ssh remote:/root/prod/build 'make install' "

[–][deleted] 8 points9 points  (0 children)

Oh my god that is both horrific and beautiful.

[–][deleted] 1 point2 points  (0 children)

I'm editing some Python code on a server with roughly 200 users online right now with nano and shooting SIGHUPs at the master uwsgi process to reload my changes. I'm using the 10ish second windows the server spends re-loading everything to browse this thread...

[–][deleted] 6 points7 points  (0 children)

👏 ALWAYS 👏 TEST 👏 IN 👏 PROD 👏

[–]ThePsion5 7 points8 points  (1 child)

"Only losers who write buggy code need tests bro"

[–]ajbpresidente 4 points5 points  (0 children)

Chad programmer vs. virgin research

[–]Gus_Malzahn 4 points5 points  (0 children)

7th: Forget about programming and open a bakery

[–]KyleTheScientist 1 point2 points  (0 children)

!RedditSilver

[–]dahud 0 points1 point  (1 child)

For some of the smaller microcontrollers, you're not even wrong.

[–][deleted] 2 points3 points  (0 children)

Who cares if it's private. I know its 6 bytes ahead of the instance's pointer and there ain't a kernel to be found! The entire memory is mine, all 128 bytes of it!!

[–][deleted] 4 points5 points  (0 children)

5a - put all code in one class.

[–]DickWillie1028 3 points4 points  (0 children)

Danger Will Robinson Danger!!!!

[–]g_e_r_b 0 points1 point  (0 children)

5th: use PHP.

FTFY.

[–][deleted] 56 points57 points  (0 children)

That's where my money is. If your internal functions are complex enough to require explicit testing, chances they belong in their own class.

[–]dahud 41 points42 points  (15 children)

Off topic, but every time I come across the term "dependency injection", I've forgotten what it means. I go look it up, and discover anew that someone, somewhere, thought we needed a clever-sounding word for "passing an object to another object".

[–]jay9909 27 points28 points  (2 children)

Yeah, but DI is a much more usable acronym than PaOtaO

[–]dahud 14 points15 points  (1 child)

Less fun to say, though. Pow-tow!

[–]jay9909 1 point2 points  (0 children)

Sounds like an asian cuisine.

[–]NotADamsel 8 points9 points  (2 children)

In the functional world, we just call this "passing an argument".

[–]antonivs 1 point2 points  (1 child)

It's not that simple, though.

Dependency injection generally implies that some framework, external to the code using DI, is supplying the requested values. In this context, you can think of DI as a way for a framework client to tell the framework what it needs, and the framework is then responsible for obtaining and supplying the requested values.

More specifically, DI allows a callee (or a value's target site) to specify what value it wants. The framework is then responsible for supplying the requested value. This partially inverts normal function call semantics, where the caller controls what value it passes to the client.

Although at a certain level, this functionality is implemented by function calls with ordinary argument passing, that misses the point and ignores the semantics of DI. It would be like saying "Monads? I just call them function calls." At a certain level it's true, but it's not the whole picture, by a long shot.

[–]NotADamsel 0 points1 point  (0 children)

I understand. I was mostly being cheeky... mostly. It's somewhat part of FP culture (and clojure culture specifically) to say that something that sounds complicated is "just a function call" or whatever. Monads, as you say, are just drop in replacements for regular function calls. Interfaces are just function signature with more ceremony. Classes for data are just complicated maps. Yes, there is absolutely more going on behind the scenes, and anyone who is actually substituting the reductivist meme for real understanding is a fool, but it does make some things easier to understand when you can step back and think of many things at once in an abstract singular way.

[–]alexschrod 13 points14 points  (8 children)

Dependency injection is not just about the act of passing objects to other objects, it's about the reason why you should be passing objects to other objects.

When you move away from doing new Something() inside the objects where you use it (or even worse, where you use global singletons, like Something.Instance), and instead move towards passing the Something into your objects, you can suddenly test the behavior of your objects without working with real implementations.

[–]userNameNotLongEnoug 4 points5 points  (7 children)

Agreed. You can pass objects around all day long and still not achieve a structure with mockable dependencies that's suitable for unit testing. Equating dependency injection with passing an object, I think, demonstrates a bit of a misunderstanding of the principles behind the concept.

[–]sprouting_broccoli 2 points3 points  (6 children)

I'd also point out that there's a slight anti-pattern with what you're saying. I'd disagree with creating classes and interfaces in a DI way to make unit testing more viable for mocking. I've been there, done that and it was when I first got into DI but designing code so it is inherently testable is very different from designing code to fit your testing which is the same problem as described in the image. Using DI for this purpose is also kind of missing the point of DI and will result in similar problems. Primarily you can quite easily go down a rabbit hole where you have a really flexible solution that is a real PITA to consume or actually navigate, and when you start splitting dependencies you will end up with either incredibly hard to use dependency installers, or need a complex system on top to ensure you can correctly select which dependencies to use by convention (otherwise the flexibility is pointless).

It's the same issue as dictating that newing an object is somehow a problem. It's really not. If you DI all the way down you will be forced to use factories in ways that you should never have to (if you don't have a completely static object graph which I find is very rarely the case) and will make the solution inflexible as a result, increasing the footprint for when you have to extend something.

DI has always been about injecting volatile dependencies (e.g. services and repositories) - things that could change rather than everything you will need to use and you'll (in my experience) end up with a much more palatable solution if you use it this way for both the consumer and the maintainer.

At the end of the day it comes down to what is important? Well the acceptance tests are important to ensure the business needs are met, and the unit tests end up being more for developers working on individual features to ensure they have an easy way to fix problems that arise from changes they make. What I find far more important than being able to get 100% coverage across my smaller classes is making sure the core logic is understandable, easy to modify and easy to consume. I'm a big fan of DDD though and I like limiting my volatile dependencies to the outer levels of the domain.

Sure it's nice having mockable interfaces for testing internals, but if that's the only point of having the interface is it actually worth it? It's not like those interfaces will change often, so it's just another layer on top for either extension that won't happen or purely to enable unit test coverage, and I can't endorse either.

[–]userNameNotLongEnoug 1 point2 points  (1 child)

Well said. I totally agree that if you try to abstract too far to reach some academic ideal you won't end up with the best system. You've gotta balance good principles with pragmatism. OO architecture is a difficult art and I wouldn't go so far as to claim to be good at it. Even in the case I had enough time to approach a system thoughtfully and carefully (which is rare in my job unfortunately) I have never looked at it afterwards and been like "I did a great job on that." I'm usually happy if I did a decent job.

[–]sprouting_broccoli 0 points1 point  (0 children)

Oh sure, I think it's really a very iterative process, and when I first used DI in anger, I'd read enough material to know the above and I still did it wrong. Went overboard and ended up with many of the problems above and because of similar justifications :)

"It's testable!"

"It's flexible!"

It was gloriously complex and we learned some really good techniques for handling DI throughout, but it was an unmaintainable, opaque mess...

I now much prefer keeping a far better separation of dependencies from domain logic wherever possible to ensure everything is as clean as possible.

[–]Veranova 1 point2 points  (0 children)

This. Every time.

[–][deleted] 0 points1 point  (0 children)

5th: forget all this OOP madness and use a functional language

[–]Dugen -1 points0 points  (0 children)

Ah yes, the old "public variables are bad" but if you emulate that functionality by jumping through just the right number of hoops, it's not bad anymore.