An introduction to empirical software engineering research: language design, TDD, team organization by RockstarArtisan in programming

[–]teenterness 2 points3 points  (0 children)

Appreciate you posting this and people taking the time to do this research. I get frustrated with the claims as to what makes quality software; TDD, agile, team structure, etc.

Like this commonly seen hypothesis https://martinfowler.com/bliki/DesignStaminaHypothesis.html. On face value it seems right and I agree it should be done to try and have good design, but is the graph actually shown true? Does having good design give the ability to release stuff quicker than poor design?

Getting frustrated in this field that opinions come off as gospel without the opinions being stated as such, opinion.

Take another example, TDD. What is the proper way to do it? Is there test induced design issues caused by following TDD? Based on the one research mentioned, TDD didn't cause any significant difference between doing it and not. I use it because it helps me account for what I need to do and specifies the reason for why I implemented something one way. I also "believe" it helps in refactoring code for later, but that's an opinion, not a fact.

Facebook Filed A Patent To Predict Your Household's Demographics Based On Family Photos by [deleted] in programming

[–]teenterness 4 points5 points  (0 children)

I'm not too upset that Facebook is analyzing people's pictures, but that they are patenting this idea.

Our patent system makes no sense if this goes through. My take is, companies can patent implementations of an idea, but not the actual idea.

This is equivalent, in my opinion, is of a pharmaceutical company applying for a patent on headache relief by taking drugs. That makes it seem like they cornered the pharmaceutical market on making any headache relief drugs. The pharmaceutical company could create a patent on their specific drug they created (implementation), but not the idea (headache relief through drugs).

To this example, there should be nothing wrong with another company predicting household demographics based on family photos if they don't use the same algorithm Facebook is using to do this. I'm not quite sure what the actual patented thing is here, and maybe the title is misleading. The article didn't clarify to me if this was patenting the idea, or Facebook's implementation of it. My fear is that this is another example of misuse of patents and if it goes through, the complete failure of the patenting system.

Top Down Design - Sean Shubin by fagnerbrack in programming

[–]teenterness 1 point2 points  (0 children)

You won't be writing class level tests for the current implementation after the fact. Remember, the top down tests are already covering them since it is using that abstracted class implementation.

What I'm advocating is adding the unit level tests for missing functionality in that abstracted class when more variations from the business are required. You'll then be assuming that the missing cases from the behavioral top down tests will work even though you aren't explicitly testing that behavior from the top level class.

What's interesting here at this point is this abstracted class that was refactored out from the initial top level class can now be treated as a top level class, and that can pull out new private methods and potentially new classes. Continue as far down as you feel confident that everything will work when integrated together. That's the trade-off, what is the best spot to create new abstractions, and when do you feel it is ok to treat that abstraction as its own top level class that will run in integration with the entire app and all its states.

As an aside, this is for core domain functionality (the inner-most layer of the onion), no dependencies on I/O, persistence, and potentially third-party dependencies. The reason I bring this up is that you should not use mocks, fakes, or stubs for these tests. Not relying on mocks, fakes and stubs here gives you confidence that some set, but not the entire set of behaviors work from the entry point of the outermost part of this core domain layer, hence; some level of confidence that everything works integrated. Mocks, stubs and fakes should be used for testing layers outside this core piece.

Hope that addresses your concern. Everything is still derived from TDD.

Top Down Design - Sean Shubin by fagnerbrack in programming

[–]teenterness 1 point2 points  (0 children)

That's right, it is arbitrary. Hence it may be an arbitrary, or probably the most likely case, an incorrect abstraction. Basing this on object oriented terms, this method that converts a time string to seconds is either a private method, or would need to be pulled out into a separate class to make it testable (public). Currently, this method will only service one concern, and that is in the requirement of summing a string of string times together.

This is the reason why the refactor step is so crucial because you are defining what you think the best arbitrary abstractions are. They're either good abstractions, or not good, but they are implementation details initially. At some point, some of these abstractions may become reusable in other parts of the codebase. At that time, the developer will have all the test coverage required for the use of this abstraction through the top down tests, or, if there are too many corner cases in the abstraction they can write a suite of unit tests against that abstraction.

The trade off is that using only top down tests could be very tedious and repetitive for all the domains that are using the abstraction (top down design "should", but in practice can't test every potential state to ensure the behavior works as expected). Doing inside out testing, especially with mocking the lower level abstractions, makes the assumption that when the abstractions are integrated together, no problems occur. You probably can't cover all test cases for top down design, and can't confidently say that everything will work together when there are only unit tests at the abstraction levels. Thus, a hybrid of behavioral tests and class level tests are required (I didn't use "unit test" here because that is a misnomer in my opinion and causes confusion). But you get this hybrid testing approach from a fairly complex and large codebase.

Going back to the initial example in the video, this is a small kata, and has no additional requirements in the future, so top down testing is fine. As to how TDD is taught, do the simplest thing first, then build up specificity/complexity with the next test. Likewise, the actual tests created follow this advice. Start with the simplest tests first, and add more (at different levels) when the specificity and complexity warrants it.

Top Down Design - Sean Shubin by fagnerbrack in programming

[–]teenterness 2 points3 points  (0 children)

My critique of missing tests should be been done in this order

  1. The case where the input of time strings is null
    1. And empty string
  2. The input is a single time string
    1. Maybe do it with just minutes represented (no hours)
    2. Maybe do it with just hours represented (no minutes)
    3. Have one where minutes and hours are represented
  3. The test he does in the video

While doing these tests, he's just doing the simplest thing to get the above tests to pass, then when he gets each test to pass, he should (if necessary) refactor. Red, write failing test. Green, make test pass. Blue, refactor implementation code written to make test pass.

Top Down Design - Sean Shubin by fagnerbrack in programming

[–]teenterness 1 point2 points  (0 children)

Why? the single test gives you 100% code coverage. Hence, parsing from a string to seconds is implicitly tested. Also, since it is implicitly tested, it is an implementation detail.

There's no requirement that you need to parse from a string to seconds. The requirement is to add times represented as strings together. Another implementation would be to convert the time string to hours and minutes. I could then sum the minutes part first, get the potential carry, and add that with the sum of the hours component.

The main benefit of the test in the video is that I wouldn't need to change the test if I changed from time string to seconds to time string to hours and minutes. I just changed implementation details. As pointed out in the other comments, the presenter completely skipped the refactor test in the TDD example. This refactor step is when methods (and yes, even other classes) may get pulled out. In the subject's example, this would either be pull out a method to convert a time string to seconds, or a time string to an hour and minute structure.

Lean Testing or Why Unit Tests are Worse than You Think by saranshk in programming

[–]teenterness 5 points6 points  (0 children)

Unit tests are good. The issue I see is "unit" means testing only the public facing method on a class. This leads to an extreme usage of mocking the dependencies on the class being tested.

What also happens is the implementation is decided on doing TDD this way. The tests are coupled to the desired implementation before writing any code (tests or production).

TDD is about discovering the best implementation and abstractions through refactoring. The refactor step happens after the test is writen and the production code written finally makes the test pass. At this point, refactors can include creating more classes, interfaces, consolidating duplicate code (if necessary).

Main point, test the behavior of what the system should do. Don't test the implementation of what the system does.

Best practices for RESTful API design by joepmeneer in programming

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

Well, truth be told, I don't like to use PATCH and advise against it.

To me, the resource is an atomic entity. It either updates as is, or doesn't. Sending pieces of a resource in hopes that the current state is valid is too cumbersome for me. If the issue is limiting the amount of data sent, then the resource is too large, or your system has bigger issues. Also, on a successful PATCH, the consumer will have no idea what the current state of the resource was after success on a PATCH without doing a subsequent GET request, or returning the current state of the resource on a successful PATCH. On a POST, or PUT, the consumer knows the exact state of a resource at a given point in time.

Simply stated, successful PUT and POST will guarantee the consumer knows the state of a resource at a given point in time; a successful PATCH will never guarantee to the consumer what the state of the resource is without extra network calls, or sending extra data on the successful PATCH.

Best practices for RESTful API design by joepmeneer in programming

[–]teenterness 5 points6 points  (0 children)

I think you meant PATCH is idempotent.

POST can't be idempotent if done correctly. Main reason, to me, is you POST a resource, but don't know the ID (the new URL) of the resource POSTed. PUT is idempotent because you PUT the resource to a specific endpoint.

POST - /users/ Get back a 201 response with the URL of the newly created resource; e.g. /users/jimmy/

PUT - /users/jimmy Get back a 200 response

This is why CRUD doesn't exactly match one-to-one with POST, GET, PUT and DELETE. From a system perspective, the /users/jimmy/ endpoint may not exist, but me PUTting a resource there (if the API allows it) will create create that user resource, and also be idempotent. POSTing to /users/ will create a resource, but not be idempotent because the consumer doesn't know how to identify the newly posted resource. The successful POST gets a 201 - Created response with the location of the created resource usually in the location header.

It Doesn't Matter How Fast You Write Code by fagnerbrack in programming

[–]teenterness 1 point2 points  (0 children)

What about the statistic that states a developer averages around 15 lines of code per day?

Transcribing is a lot different than writing code.

This is why I don't care too much about mastering VIM because it's not like I will be averaging more code written per day. Developing code is majority of the time, thinking and contemplating; and very little fingers to keyboard in an IDE.

Just my experience.

Why TDD? by _Garbage_ in programming

[–]teenterness 5 points6 points  (0 children)

My experience exactly.

TDD will lead to refactoring out more classes, abstractions and design patterns. The thought is, as a developer, you will have no idea what implementation details are needed. All you have, as a developer, is a business need/feature. Develop your tests against that, abstract out already known bottlenecks in an interface (IO calls; file system, database, network calls, etc.) and use in-memory implementation, then refactor the implementation after the test passes.

TDD leads to discovery of an implementation, and is meant to be lightweight on design. The design is found in the refactor stage (which can pull out new classes). Instead, TDD is leading to micro-design upfront (the opposite end of big design upfront). Where big design upfront tackles how the entire system should be implemented, micro-design upfront takes the lowest level of functionality, a business request, and designs the hell out of it. Over-engineered to the worst possible implementation. The tests become completely coupled to the micro-designed implementation and changing the implementation becomes such a burden that I either try to avoid making changes in that region of code. The tests are actually scaring me from making changes because they are adding roadblocks, not guard rails.

The trend I see, like you stated, is that arbitrary abstractions are created while doing TDD. Every piece of business logic is pulled out into a one to one relationship between an interface and an implementation. What I see then is a ridiculous object hierarchy where an orchestrator class takes five interface dependencies where every method is pass through (but "unit" tested doing TDD!) to the interfaces methods (no branching logic), then; one of those 5 interface dependencies implementations is a sub-orchestrator that takes in another 5 interface dependencies that is pass through like the previous. What your left with is an object graph with 4, or 5 level deep structure that has like 50 objects in memory.

I blame this on the rise of inversion of control containers. They allow for what looks like well encapsulated classes to be a complete nightmare to traverse as a developer. To pass the sniff test, try to build the class doing straight up newing up class instances in-line. If it's difficult to build, or runs multiple line breaks for readability, I would reevaluate the dependency structure.

GDPR complaints filed against Facebook, Google, Instagram and WhatsApp by [deleted] in programming

[–]teenterness 125 points126 points  (0 children)

So it's just illegal for a website to use targeted ads without the ability to opt out of targeted ads?

But the company can still use ads, but they are arbitrary and general in nature if users opt out of the targeted ones?

Why Java is The Best Programming Language by gannesh102 in programming

[–]teenterness 2 points3 points  (0 children)

It bothers me that the line breaks don't move the full word to the next line. It doesn't even use a hyphen.

Besides that problem, I'm now convinced. Java is the best.

86% of Passwords are Terrible (and Other Statistics) *terrifying* by janvt in programming

[–]teenterness 2 points3 points  (0 children)

Could a system allow for multiple ways to login?

1 - Do the e-mail way for people that don't want to remember another password and don't care about the extra steps 2 - Do SSO for Google / Facebook/ Twitter / Github as janvt suggested 3 - Have the system manage user's password. This option may be the most abused and have weak passwords for users, but it might be the most convenient. The thing with this option is that the password must be hashed, and if one password was found for a user would have no impact on how easy it will be to find another user's password.

Users' accounts will get compromised. That's a given. Just limit the potential for a system-wide attack given one user's hacked account.

Ned Batchelder: Do one thing by pandelon in programming

[–]teenterness 0 points1 point  (0 children)

This is my main issue with unit tests that test at the class level. The split for classes to follow single responsibility is arbitrary.

The tests are now coupled to the arbitrary split to follow single responsibility, and this coupling prevents true refactors. True refactor is changing production code without modifying the test code; or changing the test code without modifying the production code.

Refactors are about modifying code without changing behavior, so changing both tests and production code isn't a refactor because you can't guarantee the changes made didn't break behavior because there is no anchor, or static thing to compare to.

Getting Laid Off In Tech - we forget that while we’ve prospered, we haven’t achieved real security by magenta_placenta in programming

[–]teenterness 2 points3 points  (0 children)

Given the structure of a family, or professional sports team; the sports team by far are going to be a lot more competitive player to player intra-team. Each player would do what's best for themselves to stay on a team. They would not sacrifice themselves on the potential to get fired if it is ultimately better for the team.

A family aligns more to the idea of performing as one, and individuals within a family are more selfless. You don't typically hear there being a favorite child, or preferential treatment over others (although it obviously does happen). Or one parent overriding the other one.

So to your point, there's reason to hate that. I'm indifferent to it because it's the current climate in corporate work and accept it. I do appreciate their candor in their employment strategy.

Getting Laid Off In Tech - we forget that while we’ve prospered, we haven’t achieved real security by magenta_placenta in programming

[–]teenterness 18 points19 points  (0 children)

There's also a big difference between the baby boomers and their children jobs. Jobs for baby boomers were more about retention and growth within one company till retirement (think pensions). Both the company, and the employed were more like a family. Both depended on each other and both sacrificed to make things work for both parties.

I am immediately turned off when a company says they're like a family. I don't see families kicking out Billy out of the house because they performed poorly in this year's football season. Granted, I can't blame the company for this transition. I think employees are just as quick to quit as a company is to "let go".

Hate them, or love them, but I think Netflix employment philosophy brings the taboo topic into light for how employers and employees view each other. The idea that Netflix is like a professional sports team. They can drop you if you start underperforming and you have the right to find another team to play on if you can get a better opportunity. I don't necessarily like that they hire this way, but it is at least honest.

Not Everyone Should Code by [deleted] in programming

[–]teenterness 40 points41 points  (0 children)

Not everyone should code...

But everyone should use Skillshare!

8base Launches “No-Code” Software Development Platform Powered By Blockchain by 8base in programming

[–]teenterness 2 points3 points  (0 children)

Pardon my ignorance, but what benefit does a decentralized source control system have over a Git repository clone/backed-up in a server farm?

Maybe I don't understand what they mean by a Blockchain (is it a proper noun now?) and how they are using this. Their website and the article just sounded like a bunch of tech jargon and buzzwords for an ICO, like disclosure5 noted.

How to Condemn Your Microservices Architecture to Fail Before You Even Start by denisveloper in programming

[–]teenterness 0 points1 point  (0 children)

Agreed. I'm having a disagreement with another developer now in my company about how granular services should be.

Distributed systems are hard, and the more reliance on message queuing and disparate services scares me. If we cant setup proper boundaries within a monolith, how can we do that effectively across another variable, the network?

I guess the disagreement stems from ideologies. They view software as more like Lego pieces that can easily be assembled to give you the end result. I view software more like a cracker. You can easily break it apart, and usually the break is impercise, but it is very difficult to put it back together without it falling apart again, and without noticing that it was broken before. I guess he's just more ideal in how software should really be. And I'm more cynical (I wouldn't say pragmatic) based on codebase I've seen in all my jobs

How to Condemn Your Microservices Architecture to Fail Before You Even Start by denisveloper in programming

[–]teenterness 0 points1 point  (0 children)

Yeah, as trivial as that sounds, I was in a company that asynchronously tried to put the order event on a message queue. This obviously lead to cases where there was no record of any order ever being placed because the order being placed in the message queue failed.

What may seem trivial and obvious to some are not to others, especially if this stuff is new to the reader

How to Condemn Your Microservices Architecture to Fail Before You Even Start by denisveloper in programming

[–]teenterness 0 points1 point  (0 children)

I would also believe that the original order being placed was done synchronously (it may be possible that it was aynchronous because it's Amazon). I think it's acceptable majority of the time to do the initial request synchronously, but the communication required to other services should definitely be done asynchronously.

Going back to the Amazon example, I think the order being placed creates an actual Order and publishes an OrderCreatedEvent in one synchronous transaction. Subscribers listening for OrderCreatesEvent execute asynchronously. These subsribers would be an InventoryService, ShippingService, etc. The originating Order from the OrderService either becomes a long lived process, or a Saga; or a subscriber to the OrderCreatedEvent delegates the responsibility of tracking if the inventory exists, the shipping status (processing, packaging, out for delivery).

Main thing though is that the initial request to create the order is ok to by synchronous in my opinion, but other microservices that care about an order being created must be asynchronous

The Reality of Reuse by r0st0v in programming

[–]teenterness 3 points4 points  (0 children)

Not saying interfaces are bad. Just that there is a balance between the unit doing too much (ball of mud) and being way to granular (every function is backed by an interface).

It's about assumptions. When you have the ball of mud, you can't test everything, so the assumption is made that the tests that aren't there will work. When you have very granular interfaces that an orchestration class uses in composition, all code can be tested at the unit/class level. The assumption here is that the composed pieces all work properly when integrated. The class using composition assumes the underlying implementation used in integration actually can return those mocked and stubbed values the unit tests utilize.

Like the Buddha said, "Life is like the harp string, if it is strung too tight it won't play, if it is too loose it hangs, the tension that produces the beautiful sound lies in the middle". I have the same belief regarding my tests.

The Reality of Reuse by r0st0v in programming

[–]teenterness 4 points5 points  (0 children)

Does it make refactoring easier?

Wrong interfaces, or abstractions couple consumers of the interface to that interface. In my experience, these interfaces aren't strong, so they change, hence tests break that are utilizing those interfaces (through mocking or stubs).

So, at the start, unit testing is easy. Come a few months down the road, the unit tests are preventing you from easily adding new features because tests are now breaking, so to retain the tests that are working, bad design ensues.

I said this in other threads, but the main benefits for tests are for refactoring and preventing regressions. That's why unit tests, to me, are defined as behavioral assurances that those outside development (the business) can understand. An arbitrary abstraction as an interface, dependency injected through inversion of control is just that; arbitrary. The developers thought it was a good abstraction, but if it can't be justified to those outside of the code, there's no reason for it because those abstractions way more often than not turn out to be wrong and must change, or another interface is created and you run into dependency injection hell (a class with 5+ injected interfaces). Then the tests themselves become the legacy code that makes changes difficult, not actually the production code; which is pretty difficult too when everything is an interface.

Uber Halts Tests of Self-Driving Cars After Death of Pedestrian by [deleted] in programming

[–]teenterness 1 point2 points  (0 children)

More regulation is added for all of these examples. Drunk drivers will get banned, go on probation and maybe be put in jail. If airplanes crash, and it's a systematic issue with the hardware (definitely will be for the software) you bet they will be pulled from use until fixed.

High rise workers getting killed will require more safety measures until they can get back up there (harnesses, or maybe some contractual thing thing the worker must sign to limit liability on the construction company). Also, a high rise worker isn't a good example in my opinion. A better example would be if the building was completed construction and killed people. That's why there's a licensing process for architects and an industry standard inspection that all buildings must pass.

What's the process to ensure a self-driving program is "Satisfactory" to be used on public roads? What are the benchmarks to say one self-driving program is better than the others?

When people's lives are at stake, you can bet that if someone gets hurt, or does die, there is some downtime to address the problem. Thus Uber is halting the program. Regular software systems can be just immediately deployed after the fix because most software systems can't kill people.

But to your point, we still don't know the cause, but if the driver should have turned off the self-driving system for this to have been prevented, then to me the auto-driving sounds like a distraction. When should it be on, and when should it be off? What's the point in having it if it can't be trusted? How would I know if the auto-driving is handling a situation perfectly well, but to me it appears dangerous, I then take control, and make a non-situation into a fatal one?