> "In a competitive market for development work and staff, paying people to learn from mistakes that have already been made by many others is an unaffordable luxury; an engineering approach, derived from evidence, is a lot more cost-effective than craft development."
I disagree with this characterization. Yet again, we developers are being told to just follow the program. That programming is not an artistic or craft endeavor that benefits from experience and intuition. It is like working in a factory where coders just bang out widgets on an assembly line. And the self-appointed thinkers will optimize the process for us.
What is at risk by not allowing developers to "learn from mistakes" is autonomy. Striping developers of their autonomy is the primary cause of poor performance, not an inability to execute so-called "best practices"
Attempts to codify the process of software development always fail, because coding is a design process not a manufacturing one. Developers do their jobs in many different ways, many of which are equally effective. There is more than one way to skin a cat -- especially in creative work.
> "The labour of the cognitariate is the means of production of software systems"
This false assumption is at the base of the problem. The work of the compiler (or scp) are the means of software production. Coding is design. Once the design is complete, the results are compiled and copied to their target environments. In software, production is negligible. Which promotes the misconception that developers are producing software. In actuality they are designing software. The difference may seem subtle, but it is crucial.
This is a big mischaracterization of what "software engineering" is attempting. In this case it is an attempt to document what should be learned from experience and intuition. Because, the vast majority of software engineering IS "factory" work because its the grunt work of building what should be a well understood system, with well understood tooling. This doesn't mean that there isn't plenty of space for creative problem solving, particularly when the system is underspeced, it just means that the correct solution most of the time is the boring one.
Most companies don't want "software artists" anymore than they want "artistic bricklayers" or "artistic aerospace engineers". What they want is predictable, maintainable error free software that still works when the "artist" moves on.
That doesn't mean that your not free to upload a ton of artistic software to your github, or have opinions about how something should be designed. It just means that a professional should choose the accepted method over the fun one when given the chance. And why shouldn't they? In very few cases are "software engineers" being paid to work on their own pet projects, the end result is going to be something that the company owns and is responsible for, not the individual working for said company.
One aspect of the problem is that whenever I need to build a particular system, the parts of that future system that are well understood system, with well understood tooling take almost no work - those either are available as part of a well-known framework or can be trivially included from a well-known library.
All the work that remains, all the work that consumes most of the time of programmers is the work where either that parts of the system is not yet well understood, or where well understood tooling is not available.
I'm not seeing the "factory" or "bricklaying" work anywhere, it has been automated or converted to reusable components or frameworks. Whenever I see people spending a lot of time on systems that could be "factory" work, the situation is that it could be "factory" work if and only if the system requirements and details were properly understood, and these people were mostly working and re-working on understanding and misunderstanding what's actually needed - and there's no way around that. Once they've understood it, any "factory" work part is quick and trivial to the point of being irrelevant in metrics.
So my point is everything that we need from software engineering practices is tools and practices to manage the part that isn't "factory" work, the process of understanding the details of the systems that we haven't built yet.
There is a third class of problems in coding that, at least for me, takes most of the time - definitely more than exploratory work. That class is what I call code bureaucracy - the part where you write code that shuffles and transforms data between components, or manages components. The components themselves may be well understood and already built, but they're probably nowhere near each other and have incompatible interfaces.
Note it's not the same as "glue code". Writing glue code is a small subset of code bureaucracy, that happens only at the boundaries. True code bureaucracy begins when you discover that two components that need to communicate are on opposite sides of the system, and you need to carefully route a new path between them through half a project.
You are using "factory produced" code every time you use any optimizing compiler for typical general purpose language.
Compiler optimization phase ordering is NP-hard for every program being optimized and compiler writers cannot abstract that away to reusable components or frameworks.
> Most companies don't want "software artists" anymore than they want "artistic bricklayers"
I recently had brick laid in front of my house. When the bricks arrived, they were not cut with the precision that the landscaper had expected. They were mostly rectangular, but with enough variation in size that laying them naively (assuming they are interchangeable) would result in an ugly, uneven walkway.
The landscaper worked out what order to sort + lay them in to minimize the impact of the uneven sizes. I'm very happy he did; my walkway looks stunning for it.
If you are looking to get landscaping done, live in western Massachusetts, and appreciate someone who takes pride in his work and will take the time to do things right, I have a glowing recommendation for you. (Do be prepared to chase him down about the paperwork on both ends of the transaction; the business side of the business was not his forte). My email is in my profile.
---
I am not sure if that exactly contradicts your point. You said that's not what companies want. As a human, though, I very much appreciate work well done, when the real world inevitably defies our abstractions.
Strongly disagree, software engineering is nothing like factory work, or rather, companies who view it as such and only have "predictable, maintainable error free software" as their objective will have their lunch eaten by disruptive companies who understand software is a creative tool to deliver value and should be treated as such.
> Applying replication management techniques to creative work is a systemic mistake that actually disadvantages companies that are developing software – this is because the skills, workflows and founding principles for discovering new value are almost entirely different from those needed to efficiently replicate value.
> It should be clear that not having an effective creative management system is a huge gap in the value fulfillment cycle. If this gap remains unaddressed, the market will solve the problem by investors, over time, moving their money to entities that are discovering new value at higher rates. So, if you have this kind of systemic void, it’s really in your best interest to address the gap as soon as possible, and I would encourage you to give some serious consideration to empowering an effective creative management system.
How are you going to sell unpredictable software to a customer, and if you do manage that, how are you going to keep that customer without maintainable software?
Ask Facebook? "Move fast and break things" is in a literal sense orthogonal to predictable, maintainable software.
If you are adding value and focusing on your customer's needs, they will put up with a little more unpredictability and extra maintenance.
Again, you should really read that article, it says it better than I can summarize in an HN comment.
Part of its definition of value is that you're addressing unmet need at a rate higher than you are introducing chaos.
So the levels of predictability and maintenance in your software are tradeoffs of other ways to add value (insert "always has been" meme here). They are neither necessary nor sufficient for delivering value.
They didn't say anything about unpredictable software. There are things you can do to systemize the software development process but if you go too far you reduce the ability of your programmers to find the optimal solutions. Creating and managing complex systems is an art.
You strongly disagree based on feelings and conjecture?
As engineers, we should know to only use strong words one way or another when overwhelming evidence supports our claims, which is clearly not the case here.
I cited an article with a fairly persuasive argument around the value fulfillment cycle of creative work such as software engineering and quoted a bit from it.
> Most companies don't want "software artists" anymore than they want "artistic bricklayers" or "artistic aerospace engineers". What they want is predictable, maintainable error free software that still works when the "artist" moves on.
Well that's a bloody shame because they have to hire actual humans, and we're a smelly, imaginative lot. If they want an iron they should go to Target.
The iron is the shitty no-code, low-code solutions and I imagine it'll follow the same path the iron has. It hasn't changed much, it does the job, but if you want your stuff to look really good you take it to a specialist, AKA a dry cleaner who follows on the facade a similar process that is in reality entirely different.
Exactly I'll keep doing the creative work and let the brick laying happen on UpWork. If they confuse me for one of those then it's their loss and I'm moving on
There are so many falsehoods in this, I don’t know where to start.
1. Adding missing specs is less creative than designing a software system. It’s weird that adding specs to a product requirement is your example of creativity.
2. The correct solution is the boring one? What on earth are you basing this assertion on. Is your worldview so reductionist that you actually think this kind’ve statement contains any true or valuable information?
3. Predictable, maintainable, error-free software is more dependent on choosing/formulating the correct abstractions (which is very much a creative process) than following a checklist of “bricklaying” steps.
4. You seem to be confusing boring with correct and fun/pet with creative. Neither of these are equivalent.
It’s a shame because I assume you hold these opinions out of ignorance, which means you’ve never had the chance to build software in a creative, challenging environment where following a checklist would certainly result in failure. And I sympathize with anyone who hasn’t gotten to experience what’s truly special about this profession: the creative process.
But there is what you want, and there is what you can get.
> It just means that a professional should choose the accepted method over the fun one when given the chance.
Er, but that's rather what's being argued about, what the accepted method is. Funny that everyone making that argument tries to smuggle it in as an assumption.
> What they want is predictable, maintainable error free software that still works when the "artist" moves on.
Producing such software is the essence of the art! Managing the complexity of large software systems as they grow demands the ability to creatively invent elegant abstractions that factor that complexity into manageable chunks. Without that factoring, the complexity grows until no one understands the code -- with entirely predictable, and sadly familiar, effects on maintainability.
> software engineering IS "factory" work because its the grunt work of building what should be a well understood system
So what are you implying here? That we should go the Waterfall route and have 100% clear and finished specs? Good luck with that buddy. You're just shifting the real problem outside of your "software engineering" space.
In my 20 year career, I've never built a "well understood system".
Some things can be built 10 times faster with the right idea. Some features can be supported by a single, simple one. Some screw-ups can take forever to fix. 100% code coverage won't give you bug free software.
Building software is all about the skills of people (developers, analysts, managers, testers, ...). The better the people, and the more power you give them, the better your project will go. If you hire bad people and have to put processes in place so they don't screw up, you're in trouble.
Your post fixates on "artistic or craft endeavour" defined as something frivolous (i.e. "fun" solutions). I disagree with the use of the word artistic (and craft), but the word only appears once. Intuitively, the point is development requires a lot of "design" work that is creative, an logically so; in the same way medicine is.
In your bricklaying example, how does a bricklayer operate without an architect? The equivalent of laying bricks is typing characters.
A developer has to decide what to type, not just type it.
I think the evidence shows that "fast" software is not actually desired by the majority of companies, otherwise they would put more emphasis on using compiled languages, optimisation and reducing technical debt. Sure, everybody will take a speed improvement if it's free but most companies will go for predictable, maintainable and error free software over speed every time.
A lot of that maintainability and lack of errors will come from proper design, having a good design where the complex problem is partitioned into many really simple problems, resulting in easily testable code. And that code is easy to optimize, because it's easy to make changes when you have a decent test support.
Now this software won't be as fast as what's possible, if that is needed the optimizations will turn it ugly again in many cases, but it will be decently fast. This all starts with good design, proper intuition about which algorithms to use, and a good dose of creative problem solving.
I spun up a very simple rest API thatreturned an input parameter, and ran it under load, using asp.net and express js. There wasn't any architecture or design, it was one function. Node/express had 10x less throughput than the asp.net version, with 99% being multiple orders of magnitude larger than the asp.net version.
Of course you can hide the biggest complexity behind a single function.
What I was getting at is that if I see code with a lot of duplication, often it's not only the code that's duplicated, but the runtime as well. Then you have people using nested for loops where a dictionary would do to look it up.
Things like this, in the same language and same framework, make things on average faster, and simpler.
And if that piece of badly architected code is fragile and breaks on every change, you will stop trying to find even the low hanging fruit of optimizations that usually pay off, because every change affects multiple different files and you have no tests to see quickly if it still works.
Thinking about your reply again, it's actually the perfect example of this. Since it was a one-liner, it was so simple that it was easy to exchange it for a different one liner with a different framework just to see if it's faster. If you had to spend weeks on replacing frameworks you wouldn't have been able to do this low-hanging fruit of an optimization.
You've totally missed my point here - the fact is that no amount of low hanging fruit optimisations in the node app, or architectural improvements, or clean code will _ever_ close that 10x gap. Almost all of the decisions you make after the fact (e.g. DRY, DI, composition, and even in many cases data structures) are meaningless on both a macro and micro level compared to the very basic decisions you make - what does it run on.
What matters for companies is whether they can accomplish tasks faster than they can do them today. And it's rare that the difference between executing Python or C code is the bottleneck in that process.
"To get fast software today. You're going to need some artists." I don't think that's been true for a couple of decades. Performance issue resolution are now less "The Story of Mel" and more "throw processors, memory and bandwidth at it until it has what we need." Security requirements are more likely to be your limiting factor than raw speed. There are certainly some niche areas where you're working within tight resource limitations (I work in embedded stuff), but Moore's law means we can get MS software to run in an SoC, which means we stopped needing artists a while back.
Sounds like the software systems you are talking about are so mainstream and well understood that it might be simpler to buy something off the shelf. Now that more and more pieces are available as SaaS solution my intuition is that organizations should only focus on those pieces that are unique to the problem they are trying to solve. Rest everything should be acquired as a SaaS solution.
And yet it is exactly in the most, 'boring', 'tool constraint', 'factorized' and 'process goverened' environment of enterprise software projects that the failure rates reach spectacular heights.
The factory work is the sort of things that have been written into framework these days. Learn to use the appropriate one well and it should take away much of the grunt work.
> What they want is predictable, maintainable error free software that still works when the "artist" moves on.
That is where the craft of software engineering comes into play. It's relatively easy to make code that works. It takes a lot of experience to consistently write code that is intuitive for the next developer to understand quickly. Keeping the complexity low while keeping the same functionality is an art.
Because, the vast majority of software engineering IS "factory" work because its the grunt work of building what should be a well understood system, with well understood tooling.
I'm not sure it is, depending on which majority we're talking about.
We size in complexity because that's where the time goes, the extra testing, the rework, the long reviews, the risk.
If there are cookie cutter lessons to be learned software tends to abstract those problems away to the point they're no longer problems.
While I agree with some of your arguments, I think your main mistake is calling it "factory" work - because IMO it isn't a valid analogy (and analogies are powerful! :) ).
"Factory" work implies a far more constrained and monotone environment.
Craft work is more apt, I think.
I mean, to illustrate: Most of the work might be seen as just connecting pipes, but I'll be damned if a highly skilled and experienced plumber isn't worth their weight in gold. :)
Your right, I should have been clearer, both factory and craft imply the wrong thing IMHO.
I think a better term would have been "skilled". Like the bricklayer, or plumber you don't want "creative" so much as reproducible quality which comes from experience. So in that regard craftsman is partially right too. Traditional factory work OTOH had painters, machinist, welders, etc. All of which were highly skilled labor, but their jobs like a blacksmith making nails or plumber brazing pipe frequently were just repetitive application of that skill. One might even say that these painting reproduction shops are in this camp as well despite being "art".
So its the same with software, yes you have a framework, but the act of building out forms using that framework to CRUD up some data somewhere is frequently quite repetitive despite differing colors and button placement.
If you pay software engineers to code up a well understood system with well understood tooling you're doing something wrong imo. You should instead pay for a COTS solution. Software engineers solve the parts of your business problems that don't have well understood solutions yet.
Actually, the book agrees with you. There's very little evidence to support having a ridgid set of rules to follow when programming.
There are a few high-level take-aways from the recurring patterns seen in the analysis;
these include:
• there is little or no evidence for many existing theories of software engineering,
• most software has a relatively short lifetime, e.g., source code is deleted, packages are
withdrawn or replaced, and software systems cease to be supported. A cost/benefit
analysis of an investment intended to reduce future development costs needs to include
the possibility that there is no future development; see fig 4.24, fig 5.7, fig 5.52, fig 5.69,
fig 6.9, fig 3.31.
Changes within the ecosystems in which software is built also has an impact on the
viability of existing code; see fig 4.13, fig 4.22, fig 4.59, fig 4.61, fig 11.76,
• software developers should not be expected to behave according to this or that mathematical ideal. People come bundled with the collection of cognitive abilities and
predilections that enabled their ancestors, nearly all of whom lived in stone-age communities, to reproduce; see chapter 2.
Nice summary. Thanks. I might even skim read the book.
Sounds like a more rigorous version of Alistair Cockburn's post mortem on the non success of CASE tools. Forget the title, but the punch line is: Methodology, processes, and tooling are moot. Talented people are somehow able to make any given system work. He uses phrasing like "people are the first order determinant for success".
The book I want to read compares the folk theories and fads of software development with other democratized fields. Like education reform. How noobs, wannabes, rejects, and grifters fight over cheddar, slak, and fame. Where any consideration of form, fit, function, and ROI is ruthlessly punished and expunged.
Said another way, the only consistent thread in my career is an ever increasing number of people, who are constitutionally incapable of ever shipping product, telling me with complete certainty how I should ship product.
This is good to know. I should jump into the book. I may have gotten the wrong impression from the summary -- the quotes that I shared. I think a scientific effort to look at the many practices that are currently in vogue is very much needed. So many are taken as gospel truths and lorded over people in the name of science-- but they really aren't supported by any rigorous science at all. If this book points that out, than I am all for it.
Especially if the book has more a system thinking approach. Many studies isolate one practice (pair programming, code reviews, etc..) and can show benefits, but they ignore the systems they function in. Apparently opposite approaches, supported by the right personalities and environments can often be equally effective. From your comment, it looks like there may be some analysis like that too.
I like reading about ESE (empircal/evidence-based software engineering) for precisely these reasons. For example, someone found that SOLID programming didn't offer much of a benefit to code readability.
I didn't get the feeling that the author disagreed that programming has a crafty nature. But since building software also has some engineering aspects, he is pointing out that you (as an organization or project leader) could wait for the graduates that you hire fresh out of uni to mature into accomplished "craftsmen", or you could just observe what has already worked for others, based on evidence and mindlessly apply those patterns. The mileage may vary on your returns from the latter approach, but it will likely be cheaper and will remove some uncertainty from your projections.
Speaking as someone who has observed the kind of massive technical debt you can incur from letting your programmers mature one mistake at a time and ten reinvented wheels later, I would certainly not be too quick to dismiss the proposal.
> "The labour of the cognitariate is the means of production of software systems"
I fail to understand why you would disagree here. That sentence to me means that producing software systems requires brain work. Whether thinking, designing, coding, testing, debugging, reviewing, it's all part of the "labour of the cognitariate". Compiling isn't.
You have a valid point here. Maybe I was too hasty to judge the book by it's summary. From other comments, it sounds like this book takes a pretty reasonable approach.
I am frequently skeptical of efforts to show the "one true way" of programming, because it usually results in some poorly vetted process being forced on my at work. So, I was probably too quick to jump to conclusions.
It actually sounds like this book is good about showing that a lot of our current assumptions about good process are faulty.
The point I was trying to make about the "labour of the cognitariate" was that developer doesn't really produce software, they create the blue-print for the software (source code), and then compilers or interpreters produce the actually software. It may seem like an overly semantic point, but I think it is an important distinction to make. It changes they way you think about software development.
> What is at risk by not allowing developers to "learn from mistakes" is autonomy. Striping developers of their autonomy is the primary cause of poor performance, not an inability to execute so-called "best practices"
I've seen a lot of the opposite. Yes, coding is a design practice, but I've had to clean up a lot of messes resulting from just plain bad design because nobody involved - generally ~25 year olds with very little experience out of school - knew that there were lessons from the past they could learn about what designs would and wouldn't work.
I agree with you that programming is an endeavor that benefits from experience, and wish that people would realize that means they can learn from the experience of others. Sure, intuition is involved too, but one common thing I've seen in shitty code I've had to salvage is that people often don't apply their intuition to "how could this code fail" or "how easy will this be to modify in the future"?
That said... taking a look at this book... I don't see much in the description or table of contents that would teach those folks whose work I'm decrying above much useful about writing good software. It has sections on reliability, project estimation, and development methodology as separate things - plus a lot of non-software-design stuff. But to me, the flow is different - estimation, reliability, and delivery will all suffer if you don't have the right fundamental design skills. You can't get much better at any of those without some deeper underlying changes.
It seems to have a lot of discussion of studies adjacent to software-related things, but I'm not sold on them saying much meaningful about software design.
"and delivery will all suffer if you don't have the right fundamental design skills"
Some people will never get them. And maybe do not have to, if they are not involved in the complex design process(too much), but rather the implementation and testing of well defined small modules.
So I believe it is very important to let people do, what their talents are.
It really depends on the kind of systems and work you're doing. In my previous office, there was an entire group (about 100-150) of programmers whose job was incredibly rote. That is, you could take a novice out of college and get them up to speed in about 1-3 months to do even their most complex work.
However, the other groups were much less factory-ish, though rarely anything truly novel. Only a small cadre of programmers were working on anything that really required novelty and creativity.
It's a spectrum and that has to be understood by all participants in the discussion. Managers want everything to be like that first group, because it's so consistent and predictable. They want to know that a project will take 1000 man-hours and be right 95% of the time. Many programmers want to see themselves part of the last group. The reality is, most of us are in the middle. There are aspects of the job that are almost mechanical, and aspects which require greater creativity or "craft". If we can clarify that for the managers, it can go a long way to ending some of the nonsense.
I recognized this 20 years ago but my recognition was crude. What I noticed early on, in almost every place I worked, was most of what could be called office politics for software devs/engineers boiled down to maneuvering to work on API's or even some place lower on the call stack.
Taking a chess analogy - every new chess player is taught the same basic principles - control the center, develop your pieces and king safety. Also, some endgames are theoretical. A queen and king against a king and pawn on the 7th rank will be solved the same way by everyone including Grandmasters. At GM-level there's also significant opening theory which has to be learnt.
Yet, everyone has fun playing chess and even Grandmasters continue to be mesmerized by it because of the complexity - there is always something new to learn. Also, GMs have access to the top chess engines and can be studying using the same engine but have radically different styles.
They live for the parts of their games that are novel and so do we.
If all of our development was rigidly defined, we would just automate it. We put up with the boring parts of our development because we know there'll be parts of it that we can design.
If you are a hobbyist developer or a student, by all means, explore on your own and learn from your own mistakes. But that is not efficient if you want to get to the forefront. No GM today will refuse to learn opening theory or study the endgames.
I read that sentence as "Failures should be documented. If something failed in the past and the underlying issue why it failed is still there, it's useless to attempt it".
Ex: Using language Y for X was a disaster because of Y didn't have hardware acceleration and we were unable to reach goal Z. Before attempting to use language Y in production again, make sure platform support has improved.
I wonder how many confounding factors there are though. At one point when I had just joined a companyy, a colleague in the process of leaving told me very confidently "at our scale it is not possible to do X anymore". Obviously, we got X working the very next week.
What if using language Y for X was a disaster because of poor programming skills or micromanagers? In my experience it is very rarely as clear cut as "Y does not have hardware acceleration support" and there is not really enough rigour in the software engineering process to really figure out where a failure came from.
Sometimes software development is just cranking out a widget that you need for some line-of-business app, that isn't going to need to scale, and will never see the cloud, and will just sit there used and unchanged until the tech underneath it changes. There is a lot of software that fits into this category, done by a lot of people. Not everything gets an "Artisanally crafted with <3 by $NAME" footer on it, or is solving some novel problem of mathematics or CS.
> Striping developers of their autonomy is the primary cause of poor performance, not an inability to execute so-called "best practices"
Citation needed for this one, I've worked with more than a couple mid-level and "senior" developers who I would have sworn had never read a single article about best practices for stuff they did every day.
> In software, production is negligible. Which promotes the misconception that developers are producing software. In actuality they are designing software. The difference may seem subtle, but it is crucial.
This I agree with entirely but only for probably the top 20-25% or so of software. (Top as in most creative or most novel, not best).
Many years ago I would 110% agree that developing software was more art than science, and that the average software developer was working in a creative medium. But those days are generally over for the vast majority of software engineering needs. But this was in the days when memory was available in kb, the OS was a thin veneer over the hardware, your choices of languages were more which dialect of an machine language you worked in, and the fact that software worked at all was a miracle.
These days, with virtually unlimited memory, storage, and extremely high software reuse, the industry has been effectively bootstrapped to the point that the average software engineer is more of a tradesman than an artist - a plumber or an electrician, who's job it is to fit standard components into the space provided for by the business logic. While there are elements of creativity to that job, it's no longer a truly creative medium for most jobs. This in a broad sense was the miracle of Java.
That's not to say that there still isn't the room for beautiful, elegant, code. But those tasks are rare, and they tend to target some low-level highly reusable code that the digital plumbers can reuse over and over without any nod to artistry.
If assembly line levels of engineering are ever achievable in software engineering, then it's most likely that software engineering can simply be mostly or entirely automated and the "engineer" disappears. But that's not where the field is yet. When that's achieved (maybe in the near future!), a user of a computer can simply ask the computer to build software to perform some function based on some conversational Q&A and and entire, scalable software stack will appear out of the ether.
"Computer, I need to..." and software will appear that does that.
I disagree with this characterization. Yet again, we developers are being told to just follow the program. That programming is not an artistic or craft endeavor that benefits from experience and intuition. It is like working in a factory where coders just bang out widgets on an assembly line. And the self-appointed thinkers will optimize the process for us.
What is at risk by not allowing developers to "learn from mistakes" is autonomy. Striping developers of their autonomy is the primary cause of poor performance, not an inability to execute so-called "best practices"
Attempts to codify the process of software development always fail, because coding is a design process not a manufacturing one. Developers do their jobs in many different ways, many of which are equally effective. There is more than one way to skin a cat -- especially in creative work.
> "The labour of the cognitariate is the means of production of software systems"
This false assumption is at the base of the problem. The work of the compiler (or scp) are the means of software production. Coding is design. Once the design is complete, the results are compiled and copied to their target environments. In software, production is negligible. Which promotes the misconception that developers are producing software. In actuality they are designing software. The difference may seem subtle, but it is crucial.