• Orwell (unregistered)

    He gazed up at the enormous face. Forty years it had taken him to learn what kind of smile was hidden beneath the dark moustache. O cruel, needless misunderstanding! O stubborn, self-willed exile from the loving breast! Two gin-scented tears trickled down the sides of his nose. But it was all right, everything was all right, the struggle was finished. He had won the victory over himself. He loved Big Brother.

  • bvs23bkv33 (unregistered)

    comment n+1 will be copypasta of comment n

  • my name is missing (unregistered)

    I ate paste before I copied into this comment.

  • (nodebb)

    The swamp buries even the strongest.

  • Beezle Snort (google)

    "And the cats in the cradle and the silver spoon

    Little boy blue and the man in the moon..."

  • Craig (unregistered)

    TRWTF IMO is "SQL is not a programming language". If you have logic which is sensitive to business logic concepts (such as the flexible definition of a business day) then this should be in your app logic which generates those reports/populates a denormalised reporting table. This kind of logic does not belong in the db at all because there's no easy way to substitute a different version of that logic based on changing needs (without violating SOLID, mainly OCP).

    How easy would it be in C# to write and dependency-inject a factory service: IGetsBusinessDaysInPeriodProvider which can provide any number of implementations that share the same IGetsNumberOfBusinessDaysInPeriod interface?

  • (nodebb) in reply to Craig

    But then you can't have you junior guy that went to a report writing class (and has no other skills) build reports for you.

    Of course management never sees that if you constantly assign reports to the lowest-skilled member of the team, your reports are going to be impossible to maintain.

  • Lando (unregistered)

    Dejà vu?

  • Raj (unregistered) in reply to Craig

    Seems reckless to use the IGetsNumberOfBusinessDaysInPeriod factory service directly. Shouldn't you have a factory do that, so you can encapsulate the factory itself and make it future proof? Of course even that factory factory could be generalized, maybe you need a FactoryFactory<T> in case multiple subtypes of factory factories are needed down the road.

  • Zirias (unregistered)

    Actually, this is a perfect example why code sharing isn't always a good idea. It isn't a good idea between unrelated systems, because requirements on one system could change, but on the other they will stay the same -- exactly what happened here. So, I'd say the original mentor was right (maybe by accident, who knows). See also https://www.infoq.com/news/2015/01/microservices-sharing-code/

  • (nodebb) in reply to Zirias

    This isn't an example of the potentials of code sharing. It's an example of how the "make it work" culture makes a mess of anything it touches.

    The day someone fixed fn_CalculateBusinessDays to return total days and subtracted non-business days, instead of fixing fn_CalculateBusinessDays, they were wrong. I don't care if the report tested fine, I don't care if the business users were happy. Any sane code review should have pointed out that the change made the function behave in a way that is in conflict with its name. If the organization doesn't do code reviews on reports, then we have found the root cause.

    It is so hard to work in any proximity to a "make it work" coder. The outside world sees them as a producer and sees everyone else as a complainer.

  • MiserableOldGit (unregistered)
    It is so hard to work in any proximity to a "make it work" coder. The outside world sees them as a producer and sees everyone else as a complainer.

    They also have a very poor noise to productivity ratio, but the constant self-promoting propaganda does work for them. In my experience they are almost always huge cut and paste fanatics, makes the code brittle and impossible to quickly sort out by others.

  • (nodebb) in reply to MiserableOldGit

    makes the code brittle and impossible to quickly sort out by others

    But not for themselves, which leads to more of the "I made it work, you just sat there and complained" nonsense.

  • Peter Wolff (unregistered) in reply to Jaime

    The more urgency to hire some psychopaths and give them the "producers"'s addresses.

    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
  • MiserableOldGit (unregistered)
    But not for themselves, which leads to more of the "I made it work, you just sat there and complained" nonsense.

    True, but then I've been on several gigs where the huge spaghetti monster has fallen over under the sheer mass of tangled copypasta and they've got me in to try and fix it.

    Sometimes (rarely) they accept the argument I just need to work out the hidden business logic and re-write the damn thing from scratch ... quicker to do and good outcomes, those clients love me to bits.

    Usually I can get the ugly thing limping along, or rather, in the words of Verity Stob, "nail the corpse in the upright position". Once I just could't because it had gone too far. I suppose in either of those cases the outcome is the same as you are saying as Mr "Make it work" will claim to be the brillant genius who just needed a bit longer and not to be bothered by this so-called external egg-spurt.

  • Colin (unregistered)

    It's actually neither an example of why code sharing is/isnt a good idea, or how "make it work" culture makes a mess of everything, IMHO. I believe it is a good example of how, in our line of work, a one-concept-fits-all approach just simply doesnt work in real life. Neither code-reuse at all costs, nor make-it-work. Programmers who blindly copy and paste code routines multiple times into different methods without realising that a common method would be better are both no better or worse than those who are determined to re-factor an application to within an inch of its life in pursuit of the perfect technical design regardless of timescales and delivery dates. I find a more pragmatic approach fits better, re-use where appropriate, comment all such "utility" methods to within an inch of their lives to make their function completely obvious, educate the team in the existence and use of such methods, and make it clear that they should always be used if appropriate and not modifed without checking with the rest of the team.

  • (nodebb)

    This is actually a very important question. Application business logic tends to be slower. Then you write the results to a denormalized reporting table, it has to be invalidated, like any other cache. Keeping business logic in DB has its own problems, like lack of compilation (partially addressable with SQL projects).

  • ExperiencedDBA (unregistered) in reply to Craig

    Holy WTF...business logic belongs in the database and nowhere else. In a well designed system, you don't have any CRUD operations in your code but just calls to encapsulated database functions...PL/SQL, T-SQL, whatever. One call per transaction, no moving huge amounts of data between layers. But of course today that has all been sacrificed on the altar of "database independence" (i.e. software that runs equally bad on any DBMS). If I had a cent for each developer I told which statement he's have to optimize and how, only to get the answer "we cannot change the SQL; it's all generated"...

    And that attitude of "eh, it works" is spreading even among so called "database professionals". Just debugged a PowerShell script that ran painfully slow...well, when you get a list of "all windows server objects" (several thousand) from the monitoring system, and then locally filter out the one with the name you are interested in - of course it's slower than telling the server "get me all objects whose name includes xxx" (a few) and then locally filtering out the one that is a windows server. A DBA not using the database to filter...

  • xtal256 (unregistered) in reply to Jaime

    "It is so hard to work in any proximity to a "make it work" coder. The outside world sees them as a producer and sees everyone else as a complainer."

    I can relate to that. I've worked with those kinds of people and I was seen as the complainer. Unfortunately, I was the only "complainer" on the team, which meant I was "not a good fit" for the team. Now I work in a team of one and am much happier :)

  • Some Ed (unregistered) in reply to MiserableOldGit

    Oh god, I still remember the first time I nailed a corpse in the upright position to get time to fix something properly, only to have my boss phone up 5 minutes later. "I see you fixed it! Good job! For your next assignment..."

    Pro tip: if you want good relations with your emergency contractors, even if they have fixed something, if they've been working 12 hour days for a couple weeks to get to that point, give them more than 5 minutes of rest before their next assignment.

    If I recall correctly, I didn't scream, just laughed. Then I explained. I don't remember exactly what I said to get him to actually order the stuff I'd said he needed to order, but I'm pretty sure 'unrecoverable catastrophic system failure' was part of it.

  • Barf4Eva (unregistered) in reply to ExperiencedDBA

    That really depends... I'm a bit of a DB nut and sometimes enjoy having my business logic at my DB layer for the added integrity it enforces or the performance benefits gained. But this all depends on the source of data being operated on, the volume of data being operated on, and where the particular business logic will have the largest impact.

    I also have business logic in the application, sometimes not in one layer, dependent on where my needs should be met for a particular problem. Decoupling is healthy, but it doesn't mean you have to throw out business logic at the DB layer just because you are also enforcing business logic in an application layer.

    I'd argue it makes sense to have business logic at multiple levels, within reason, careful planning, and proper execution. Just picking a side and sticking to it is too much fanaticism without concerning oneself w/ the implications.

  • AnotherDBA (unregistered) in reply to ExperiencedDBA

    Dude thank you for this. So many developers firmly believe that ‘code is faster’, no matter what it’s doing - to the point of mass data movement and auto-generated SQL that looks like a horror show when it hits the server (Link2SQL lives in my nightmares).

    Re: ‘producers vs complainers’ It’s really becoming a challenge to even communicate the difference to non-technical management. I can only hope that, at some point, companies somehow begin to realize how much productivity is wasted, following hype-men down the toilet. I don’t know how to solve that problem.

  • Jeff 11 (unregistered)

    It’s fine to have business logic at the database level... as long as it isn’t used by the application.

    Why? Because then your app developers are dealing with an unknown set of functionality and grammar that can change over time and become out of sync with expectations. Implicit, undocumented dependencies are introduced and lines of responsibility are blurred.

  • D (unregistered)

    This particular example is a good illustration of where complexity hides. You start with the assumption that there are five business days in the week, then someone tells you need to account for holidays... and there are different types of holiday, some counting as business days in some circumstances and not others. And then you realise that some holidays are local, so you have to take into account where the customer is located, or maybe multiple customers... and all your efforts to avoid code duplication give way to the urge to beat your head against a wall until things start making sense again.

  • ichbinkeinroboter (unregistered) in reply to ExperiencedDBA

    amen!

  • ichbinkeinroboter (unregistered) in reply to Barf4Eva

    amen to that too

  • 🤷 (unregistered)

    Sometimes it's really much more convenient to just copy/paste something and change it to the project's needs. I know I've created functions that worked perfect for one application... but where pretty much useless for another, because the underlying code was just too different. So, what do you do? Why, write a wrapper, of course!

    On the plus side: It REALLY made changing the business addresses a lot easier, as there was only ONE place, instead of a few hundred, where it needed to be changed. And yes, changing addresses was a common occurance at my old job.

  • (nodebb) in reply to D

    I also thought of variable, and/or local holidays… IDK much about holidays in the US, but in Germany there are not only differences between the federal states (often related to whether the state is or used to be predominantly Catholic vs. Protestant), but even within states – e.g., the city of Augsburg in Bavaria is the only one observing the local "Hohes Friedensfest" ("high celebration of peace"), on which the end of the Thirty Years' War is commemorated… yes, a war that ended over 370 years ago.

    And, as for variable holidays, the date of Easter is calculated according to the phases of the moon. If you want to make your software completely future-proof, a solid knowledge of lunar astronomy could be advantageous. ;-)

    Addendum 2020-02-20 05:32: As a sidenote, Pentecost is celebrated exactly seven weeks after Easter Sunday, so its date also depends on the moon…

  • guest (unregistered)

    Well that was quite unfortunate timing of an article with that title considering the creator of copy paste died today.

  • (nodebb) in reply to D

    This particular example is a good illustration of where complexity hides.

    Yup. And that's exactly the reason for it to be in a reusable function. Copy/paste would lead to increased maintenance effort. Also, the additional complexity belongs in the function, not in the caller. If you have twelve different definitions of "workday", then your function should allow the caller to pick its definition by passing a parameter.

    Here's a real scenario I've seen. A call center I worked in had the same problem everyone has of "what are this year's holidays for this company". We used that definition when figuring out if we were on track for our goals. 15 of 21 days down in the month, 6 to go, we should be at 71% of goal. However, call center performance reports included Saturdays, where we had a small crew. We didn't apply standard metrics to Saturday because it wasn't a workday, but we didn't filter Saturday out of the report entirely, because it was a "workday" by a different definition.

  • (nodebb) in reply to ExperiencedDBA

    Holy WTF...business logic belongs in the database and nowhere else.

    I fell off my horse and hit my head on the butter churn when I read this. Are you still living in 1985? Do you realize that most modern language can do true set-based operations without loading the entire data set in memory? How do you scale your "business logic goes in the database" idea out beyond a single database server? Do you realize that writing business logic of any complexity in the DB makes it many times more difficult to build, test, and debug?

    I have never written a database agnostic application in my life, yet I constantly see the middle-tier languages evolving faster than database languages, so I have moved much more of my heavy lifting to application servers.... which satisfy all of your demands for centralization without binding me to horrible programming languages. There is no architectural difference between putting your business logic in stored procedures and putting your business logic in application servers, but there is a huge practical difference.

  • doubting_poster (unregistered) in reply to ExperiencedDBA

    "Holy WTF...business logic belongs in the database" This is the biggest WTF I've read in the comments here to date... A database is good at storing and retrieving data. Not executing logic. Plus, in any kind of serious production environment the database can be hammered to bits and doesn't have time to waste on executing business logic... Business logic belongs in the backend part that's meant for running logic, NOT the database.

  • Cameron (unregistered)

    Today, of all days. RIP Larry Tesler

  • Prime Mover (unregistered)

    We had a system where the algorithm to calculate the number of business days was a central utility, but the business logic to determine which specific days of which specific year were holidays (invoked by the central utility) was implemented on a per-customer basis. It was up to the customer to inform us which days of the year were holidays for whichever outlets controlled by that customer. It boiled down to being a short text file containing the dates. If no such file was found, a default list of public holidays was used for whichever region was relevant to that customer. Fortunately our business model was built around the notion that each customer had a well-defined region with well-defined boundaries, and the fact that the customer was obliged to submit to us certain crucial information about the changes to their business operations every year.

  • tlhonmey (unregistered) in reply to ExperiencedDBA

    "But of course today that has all been sacrificed on the altar of "database independence" (i.e. software that runs equally bad on any DBMS). "

    No, it's been sacrificed on the altar of stupidity and laziness. If you need your code to port easily between SQL implementations then you pick a language that has good SQL abstraction libraries for your intended potential targets, write your business logic code in that and export an API for your applications to talk to, and don't let anybody talk directly to the database. There may still be a performance hit, but it'll be a lot smaller than letting every bozo who thinks he knows how to code filter his entire dataset through his workstation on every pass.

  • linepro (unregistered)

    There are even better ways to mess this up.

    I once worked at a place where the "buzinezz logik" was in stored procedures that were fired by insert / update / delete triggers.

    This covered field modifications and cascading updates on other tables.

    My main preoccupation was fixing Deadlocks and Livelocks....

  • Zed (unregistered)

    Good to see an Alex article

  • Yet another Rick (unregistered)

    I was new on the job managing a largish UNIX cluster running Oracle and sat next to a couple of the DBAs. One morning I heard them arguing back and forth about why the wrapper script that was used in every job running under the scheduler was dying and spitting our a particular error message. They couldn't understand how the job was failing at the point that the error message told them it was at when the database was telling them that that step had been successfully completed. After a couple of hours of pulling out their hair, they were to the point of considering opening a TAR with Oracle. After lunch I asked them how that problem was coming along and they finally asked me if I'd take a look at why the script was showing a failure had occurred. The script was fairly large as it did sanity checks on the arguments supplied to it (for example, "Is this a SQL script that's supposed to run or a procedure?") pretty normal Ksh stuff. They'd printed it out (maybe a dozen pages) and highlighted where the script was failing. After about ten minutes of skimming through their script I noticed that every time they wanted to issue a message, they'd cut-n-pasted the same few lines of code to generate a timestamp and display the error/diagnostic message. The highlighted error was fairly early in the script. I noticed that, about 3-4 pages later, the same error message was being displayed (where the actual runtime error was occurring). Oops! Whoever decided to add that error message farther down had failed to change the text of the error message. My suggestion to them was to rip out all the cut-n-pasted code and insert a 3-4 line function at the top of the script to be invoked when they needed to issue a message. The hell of it was both of them had the O'Reilly Ksh book on the shelves in their cubicles. They must have skipped the section on functions.

  • joderor (unregistered) in reply to ExperiencedDBA

    is this a fucking joke? like, seriously, are you kidding?

  • (nodebb)

    This is why a requirement and a use-case are two radically different things.

Leave a comment on “Copy/Paste Culture”

Log In or post as a guest

Replying to comment #:

« Return to Article