Saturday, September 29, 2007

Compiler Mania

So I know I talk a whole lot of shit about what I want to do, but I believe that I have it figured out now. All the work and reading I've done lately on the future and history of programming languages has led me to compilers. I'm going to start reading and reading and reading about compilers, and write some. I've done it before, but I'm going to kick it up a notch, BAM.

In 2000 I took a compiler course from Doug Lea and we compiled a simple language into Java Byte Code. I still have the code around for that course, and tomorrow I'm going to find it and review it like a madman. I don't think I have the language syntax definition any longer however. It was on Doug's site, but now its been replaced by MiniJava. I'll likely be learning a lot about MiniJava as well.

I'll be reading two books: Compilers: Principles, Techniques, and Tools (2nd Edition) and Modern Compiler Implementation in Java (Hardcover) The first is the classic Dragon Book. I have the first edition, but hopefully I'll get to pick up the second edition soon. The second, despite its poor reviews on Amazon and the fact that its slightly outdated, was recommended by Doug Lea, so I'm thinking its a safe bet.

For some reason I just feel compilers is the place to be. I know I can compile to JBC, and I know so many new languages are going to be compiling to it to run on the JVM. I want to be a part of that. I have a lot of interest in new languages. I know I don't want to be stuck in the Java world forever. I want to be a guy leading the new language revolution. I want all languages to have instant IDE support. I want to make it so you don't have to do much more to create a new language than just define your syntax and plug in to an IDE.

I can do it. Follow me and on my ride as I detail as much as possible on what I learn.

Thursday, September 27, 2007

Pair Programming Problems

Today I got to pair with the ThoughtWorkers in our group. Being a former ThoughtWorker, we worked really well together. You could say we were on the same page, and level. When you're on the same level, and the same page, work just flows. So that leads into what I want to write about - what happens when you have to pair with someone who's either on a different page, or a different level than you. I'm not an expert at pairing, but I've certainly noticed that these two problems occur, and I've thought through them a bit.

Lets start with someone being on a different level. This is the obvious one and easy one to explain. Simply put, for the person who's more senior, it can be frustrating. You have two choices, slow down and teach the other person, or leave them behind and forge ahead doing work while they watch. Of course, you can only do the latter when you're at the keyboard.

The first approach is better since you bring up the level of the other person; the second approach isn't even really pairing. But, the first approach is problematic. Eventually, you get burned out of teaching. Especially if the person just seems slow, or stubborn. You could get rid of those people of course. There is a way to solve this though, switch pairs frequently. That isn't something that hasn't been said and done before of course. I'm just reiterating it because we don't switch nearly enough at NYSE.

In deadline situations however, it might just be better to take the reigns and plow ahead.

Onto the next problem, pairing with someone who's not on the same page as you. This could be in any way imaginable. Here are some examples:
  • They are old and lame, and you're young and cool
  • They like using Debuggers (lame), you like writing Unit Tests (cool)
  • They like checked exceptions, you like unchecked
  • They chew gum with their mouth open and you just want to smash them
  • A bunch of others
What can you do about this? Its a bit harder to deal with than the first problem. Of course switching pairs more helps, but you still have to be productive while you're pairing with this person. So, You have to try to find some middle ground on some things. For instance, if they like the debugger, and you like unit tests, write a test, and run the debugger in the context of the test. In order to find this middle ground, you're going to have to communicate well, and constantly. Pairing in this case is a bit much like a relationship, or a compromise. Both sides are usually unhappy, but in general things work out.

There is another problem I've noticed with Pairing and Legacy Code. Much of the time, you have to look through the code slowly to figure it out. Either person might want to look at different parts of the code. Its frustrating to have ideas about what the code is doing, and if you're not at the keyboard so you can't look at that area. It seems that its almost better to split up, review the code, then come back together to do the work. This presents other problems though. Sometimes while trying to figure out the code, you'll want to write tests, and refactor. But that is actually contributing to the work. I'm not articulating my thoughts exactly as I want to. If you split up and do work you aren't pairing. Thats not good. Ugh. I guess the whole point of that is that its difficult to pair and read legacy code.

Lets really quick review how to fix the problems:
  • Switch Pairs regularly
  • Communicate a lot
  • Teach people to bring them up a level
  • Don't worry about plowing ahead with a huge deadline looming

Tuesday, September 25, 2007

Language Explosion

I've said it before, and I'm not saying anything that people a lot smarter than me aren't already saying better, but I'll say it again anyway.

There is about to be a language explosion.

In many ways I have No Fucking Idea what I'm talking about...but something weird says that in five years time I'll have made the right moves by just attempting to talk about this today. I may be repeating myself, but each time I do, I get more ideas.

Any two important questions that need answering.

What can make this possible?

I've hinted on this before.
  • JVM
I can't back this up at all. But, certainly there's JRuby, Scala, and other projects. The JVM is a great tool. I'm so lucky to have written a compiler in college that produced Java Byte Code. I will be reviewing that code soon. I think many many languages will be compiling to JBC. Its so simple to do so. Boom, instant, multi-architecture runtime.
  • IDE Support
As IDE's mature, they will be able to take on new languages just with a compiler plugin. Maybe at first they will somehow only take on languages that compile to JBC, I'm not entirely sure. But, I assure you, its going to happen. Boom, instant IDE.
  • Library Support
Languages that utilize libraries built in other languages are in better shape that those who don't. That much can't be denied. There are a few interesting comments that I have on this.

Scala, for instance, has compile time access to Java classes (which, if you reference the last point, has IDE access as well). Someone had to write a Scala compiler to allow this to happen. Those points in and of themselves are not too interesting. But they do lead into something much greater.

Once Scala compiles down to JBC, then its accessible to Java code. Someone writing Java in their favorite IDE can drop in a Scala jar file, which is really just a Java jar file, and have full access to it. I'm very curious as to how this works. What does the JBC look like? How can you link to the source code? Do they line up? How can they?

Anyway, we still arent at the truly interesting part. Any new languages compiling to JBC, you guessed it, Boom! Instantly accessible to all other new languages also compiling to JBC. Ok maybe not instantly, you still have to write the compiler. That is the interesting point. New languages, designed for different purposes, designed to make different aspects of development easier, all with accessibility to each other. All tied into the IDE. Oh man.

So let me summarize all that.

  1. Choose a syntax that fits your problem.
  2. Write a compiler that understands Java.
  3. Compile to Java Byte Code
  4. Write a compiler plugin for the IDE, or write your compiler to fit some special IDE compiler spec.
  5. Plug in.

Maybe I'm nuts and thats so far out of wack, or so far off in the future, but I can see this happening in 5 years.

Is there a way to capitalize on this?

As I see it, there is a whole bunch of work that needs to be done, but it will get done.

  1. IDE's need a way to understand new languages. This could be through a compiler plugin, or Abstract Syntax Tree plugin or who knows, just something else.
  2. People still have to write compilers.
Guess what, its that last part thats going to be the bomb, the explosion, the Oh Mama. How?

Writing compilers is hard work. No doubt about it. There needs to be generic compiler libraries that a compiler writer can use to to easily create compilers that do all this stuff. I'm not just talking LEX and YACC. I'm talking easy API's to do the following:

  • Give access to all Java code.
  • Provide the hooks to the IDE
  • Compile to Java Byte Code
The compiler writing is whats going to take the most time in this language explosion. Tools to make this thing easier are going to be used like mad. Maybe I'm crazy. Maybe its already been done. Maybe I'm just shooting my mouth off. But, I do know I'm learning. I do know I came up with all of this all on my own. I do know I'd love to have someone give me some ideas on it. I do know its just sort of flying out of my mouth and isn't completely well written. Sorry. I'm just excited.

Thursday, September 20, 2007

Progress on Goals

So admittedly, I haven't made much progress on my goals the past few weeks. I've been concentrating on CruiseControl. Unfortunately I think I'm going to have to revise them. The problem I'm having is that I'm so random. One day I'll be reading Spring and the next I'll be reading the History of Programming Languages. So what I think I should do is just write down anything and everything that I'm interested in. Here they are in no particular order:

  • History of Programming Languages
  • Scala
    • Scala Eclipse Plugin
  • Smalltalk
    • Squeak
  • Spring
  • Unit Testing
    • TestNG vs. JUnit
    • Unit Test Creation
      • Agitar
  • Concurrency
    • Testing Concurrency
  • FindBugs and the idea of FindBugs annotations
  • Developing new programming languages
    • Problems developing them
      • Library support
      • IDE/Refactoring support
      • Automated Unit Test creation support
  • Web Frameworks
    • Seam
    • Struts 2
    • Spring whatever
  • TDD
  • BDD
    • JBehave
  • Companies
    • ThoughtWorks
    • NYSE
      • How Stock Exchanges work
  • CruiseControl
    • Why CC Java Sucks Eggs
      • Why the new Dashboard isn't useful
  • Build Process
  • Extreme Programming
  • Dependency Injection
  • Aspect Oriented Programming
  • Compilers
    • Compiling to Java Byte Code
    • Compiling in IDE's
    • Building Compilers
    • AST
  • Operating Systems
  • Virtual Machines
  • OO
    • Design Patterns
    • Refactoring
    • Future of OO
  • Java
    • Annotations
    • New JSR's
    • Backwards Compatibility vs Forward Mobility
  • People
    • Doug Lea
    • Kent Beck
    • Martin Fowler
  • Legacy Code
  • Teaching
    • Agile Enablement
    • Giving Presentations
  • Constructors Considered Harmful
  • OSS Projects
    • I really need to get on one
  • Technology Evaluation
  • IDE's
    • Building Refactorings


Legacy Software

The main problem with moving forward with legacy software is that it takes so much damn time to get classes under test. So when ends up happening is, you load the entire system just to test one tiny little bit of it, and you end up with all sorts of different testing issues, further contributing to your original legacy code problem.

Why is it so hard to get a class under test?
  • Idiots.
Thats all. Thats the only reason. I feel like this should be the end of the post, but I suppose I'll trudge on, I haven't posted in a while.

Classes have complex dependencies that interact with each other constantly, handing each other other sets of complex Objects, making anything difficult to stub or mock out. I'm reading Working Effectively With Legacy Code and its helping, but these things take time. I think I'll get there, but maybe not for another year or so.

Brown Bag Lunch: Results

I guess a week went by since I wrote last, about the presentation I was going to give on CruiseControl. It didn't seem like a week at all. I was so busy getting ready for it, putting together slides, writing, and practicing, that the week totally flew by.

Everything went over great. I'm pretty certain everyone is going to start using CruiseControl, I got positive feedback on the implementation, I definitely won over a few people who want to help, and I may have gotten it into everyones heads that we should all be giving presentations. I'm not sure which of those things is the most important. I guess it doesn't matter.

Thursday, September 13, 2007

Brown Bag Lunch: CruiseControl

As a direct result of my own brainstorming on technology evaluation, I've decided to follow up on my own advice. I'm going to give a follow-up presentation to my bosses presentation on Continuous Integration. Mine is going to be directly oriented towards setting up Cruise Control, where as his was just a high level overview. I'm going to brainstorm some ideas right here on the spot, in outline format.

  • Intro
    • Brief overview of what this presentation is about
      1. Follow up on Mike Roberts' Continuous Integration presentation
      2. Brief refresher on what CruiseControl is
      3. Will go over the internals of CruiseControl
  • Part 1: Overview
    • Overview of CruiseControl capabilities
      1. Update from CVS
      2. Run Ant
      3. Show test reports
      4. Scheduled Builds
    • Overview of what projects are currently in CruiseControl
    • Internals of CruiseControl
      • config.xml
  • Part 2: To do List
    • Determine what artifacts need to be published
    • Get performance tests running in CruiseControl
    • Get genversion running daily in CruiseControl
    • Get Unit Tests working through Ant
    • Get Emma and FindBugs reports integrated into CruiseControl
  • Part 3: What is required of the team
    • Install CC Tray
    • Write tests
    • Commit frequently
    • Don't check in broken code
    • If you break the build, everyone will know, so fix it.
  • Outro
    • Challenges
      • Challenge others to give 30 minute presentations
      • Challenge Dave Litner to make others give 3o minute presentations
      • Mention Technology Evaluation
  • Questions
    • Questions can be asked throughout, but try to get more questions at the end.
I might come back and edit this, but its a damn good start.

Wednesday, September 12, 2007

Approaches to Technology Evaluation

I'm going to keep a running tab for Approaches to Technology Evaluation in small companies with small budgets, and tight schedules. This list should be full of ideas to do it and keep it affordable. This list doesn't really even have to be about software, it should apply anywhere.

  • Brown Bag Lunches
Pick a day each week, any day, and have everyone each lunch together for an hour while someone does a presentation on a new technology. Rotate the presenter, so even on a team as small as five everyone has five weeks to prepare. This is plenty of time. I think this can be a very effective, inspiring method for evaluation, and it has side effects of getting everyone involved, everyone gets to learn, and you build better moral.

  • Dedicate at least some actual work time to it.
Dedicate someone to it one day a week. Obviously this is a slightly more expensive approach. The company is actually paying for it. But, it guarantees that you get some quality time into it. The previous approach could easily break down it people don't want to spend much time at home. You have to judge your group.

  • Partition Work
If you partition your work properly, into independent modules, then you should be able to choose any module and build it using entirely new technologies, or just one new technology, keeping others around. This shouldn't cause dependency issues because the modules are separated.

This will have costs. At the least you need to do a minimal amount of evaluation, and spend some time up front learning new technologies chosen via evaluation. You may also find that the new technology is no good after you build, and have to rebuild using your older technology. If you're working with more than one new technology, you may run into a situation where you're unclear which technology is bad, and might mistakenly decide all of them are bad.

  • Force out old technologies
Choose a number like 5. Any technologies older than five years old are considered legacy tehcnologies, and under no circumstances should you continue any work with that technology. This approach is far more expensive then the others listed. But one that promises to ward off stagnation.

  • Force in new technologies
Slightly similar to the last approach is forcing in new technologies. This doesn't mean forcing out old ones however. It means you maintain the legacy technology, and proceed with development on the new technology. This can lead to maintenance issues, but I tend to think that developing further with the old technology leads to more issues.

Both of the last two approaches aren't really evaluation approaches, they need to be used in conjunction with an evaluation approach. But, having either policy will certainly stimulate the evaluation.

More Ideas To Come!

Innovation vs. Masturbation

Heres a thought that I'm sure many other people have had: Technology companies that are not dedicated to technology evaluation and adoption fall behind, and get bogged down with legacy software.

Lets say a piece of your system is horrendous, and it uses 8-10 year old technology. Lets also say that you have a new project coming up. My theory is this: If you don't evaluate new technology because it would introduce another maintenance variable into your system, then the new project will fail. Why? Because the old technology IS a maintenance variable! Even if you keep a close eye on the development of it, its still going to get out of hand. Why? Because its not good technology. When you have something difficult to do and the technology doesn't quite support it, you do a "Workaround", thinking, "Well, we'll fix that up later". Well, THERE IS NO LATER.

Most companies have there so called "valid" reasons not to do it yet. But I think for the most part none of them are valid. At the very least you need someone looking at new technologies. Yeah, its expensive, but you're not going to make significant advances in productivity without it. Is there some risk involved? Absolutely. Is the risk greater if you don't do it? My bets are on yes.

This is all similar to Innovate vs. Litigate, where a large, aging company (ie Microsoft) sues everyone in an attempt to hang on to dying technology, instead of focusing on creating new, great technology.

I prefer to call it by a slightly different name however
: Innovation vs. Masturbation. I could explain, but I think you get the idea.

Sunday, September 09, 2007

New Language Adoption

I have some thoughts on language adoption as I've done some preliminary work learning Scala, and having learned a bit of Ruby, and a lot of .NET, all in the past 6 months. I'm going to focus here on Scala and Ruby.

One unfortunate problem with adopting a new language is the lack of quality libraries, or the total absence of libraries, and another is the lack of IDE support, especially refactoring.

  • Libraries

Its probably the case that many languages suffer for a long time, and never make it because they are lacking libraries. Ruby seems to have gotten over it somehow, despite starting from scratch. It took 10-15 years for it to catch on however. Clearly starting from scratch was Hard. If a language can make it from scratch, you know its special. (I should look into JRuby because I wonder if that somehow gets Ruby access to Java code. I don't think thats the case, I think its just compiling Ruby into class files to run on the JVM)

Scala gets over this problem by having full access to all Java libraries. However, I suspect that in doing so you have to sacrifice some potentially high quality features. For example Scala code is allowed to call Java constructors and as I've mentioned a few times now - theres something fundamentally flawed about construction in general. DIF's exist simply to solve that deficiency in the Java, but in the end, the language is still flawed. Does that mean the flaw carries over into Scala? I suspect at least somewhat. I'm going to continue researching this.

Either choice, from scratch, or library inheritance poses its issues. I'm not sure which way I'm leaning at this point.

  • IDE Support
Both languages suffered from lack of IDE support. Both had to take the start from scratch approach on this issue. I downloaded the Eclipse plugin for Scala, and its pretty minimal. No refactoring support, and many other features are missing. I remember doing the same for Ruby when I was applying to Thoughtworks.

This leads to to an obvious question: Is it possible to avoid this approach? That is, is it possible to create a new language that leverages existing IDE support? I suspect that it is, but I'm certain some research needs to be done on it.

IDE's are essentially compiler based. And Eclipse in particular is completely pluggable. What if you could plug in the compiler? It it possible to write refactorings generic enough that given the correct compiler, the refactoring could work across any language? Possible I assume, but difficult. Many Eclipse Java refactorings for example, simply print out Java code and then have the compiler recompile. These refactorings certainly would not work on other languages.

It might not be possible at all, but its certainly worth looking into. Until then early adopters will have to suffer though lack of support, until someone (quite likely them) builds that support. Language adoption will continue to take some time.

Wouldn't it be nice if anyone (well, anyone that can write a compiler) could create their own language and have it automatically fully integrated into an IDE with full refactoring support and all the other features? Then all we'd need is support in the IDE to easily create new languages and compilers. Then we'd be looking at thousands of languages that we could possibly adopt. Domain specific languages would be so much easier to create. So many possibilities I should really just stop talking.

Saturday, September 08, 2007

Next Generation IDE Technology

Certainly IDE's have automated refactorings, and they are so nice, but I'm thinking the next generation software is going to:
  • examine your code
  • determine what variables are related to what responsibilities
  • identify classes with more than one responsibility
  • identify classes in need of dependency breaking refactorings
  • refactor the code with minor intervention
  • compliment the refactorings with a full suite of unit tests that ensuring equal behavior
Additionally, as you type new code, you'll get real time warning messages such as, "It looks like you're adding unrelated behavior to this class, I recommend you do such and such..."

Following soon after, languages that enforce this at compile time. "Compile Error: Too much responsibility in this class". Additionally, "Compile Error: No unit tests for methods X, and Y". The IDE's will then tie into the unit test generation code like Agitar, and write legitimate unit tests for your code. You might think thats funny, and it might be annoying sometimes, but I bet it makes for cleaner code.

Then, people who haven't read a million books, and have 10 years of schooling can actually write code without subtracting value. They will be forced to do things correctly, and it shouldn't sacrifice creativity like a strict methodology.

Goals Revisited

For a few reasons, I think I'm going to drop everything and learn AOP, and some DIF's including Spring, Guice.

I need to do this for the following reasons:

  • There is something entirely unnatural about constructing objects in Java.
  • I need to learn how to break dependencies better.
  • I need a fresh view for looking at Unit Testing legacy code.

Stay tuned for more info on all of those items.

Problems with Dependency Injection

I'm having an issue with Dependency Injection that I need some clarification on.

I have a static factory method that takes a parameter:

public static GeographicalMap createGeographicalMap(String inputMap) throws DuplicateRoadException {
    GeographicalMap map = new GeographicalMap();
    return map;

Its perfectly possible to use static factory methods in most DIF's. The problem is, the parameter won't be known until runtime, so it can't be configured before runtime. So, how can an object that uses a GeograpicalMap have the GeographicalMap injected into it?

One solution is to remove the "known at runtime only" parameter from the static factory method, and expose the initialize method. The client code then becomes:

GeographicalMap map;
public GeographicalMap getGeograpicalMap{ return map; }
public void setGeograpicalMap( GeograpicalMap map ){ = map;
public void someMethodThatUsesMap(){

This does not sit well with me at all. I have to break encapsulation, and return an object that is not fully initialized. Clients have to remember to initialize the map before using it, precisely the reason why I added the static factory method to begin with. (As a simple side note, I prefer static factory methods over constructors for readability.)

I'm certain someone must have solved this issue without violation OO principles so badly. I am determined to find the right answer.

Thursday, September 06, 2007

Book List

Refactoring: Improving the Design of Existing Code Refactoring: Improving the Design of Existing Code

Test Driven Development: By Example (The Addison-Wesley Signature Series) Test Driven Development: By Example (The Addison-Wesley Signature Series)

The Pragmatic Programmer: From Journeyman to Master The Pragmatic Programmer: From Journeyman to Master

Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley Professional Computing Series) Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley Professional Computing Series)

Effective Java Programming Language Guide Effective Java Programming Language Guide

xUnit Test Patterns: Refactoring Test Code (The Addison-Wesley Signature Series) xUnit Test Patterns: Refactoring Test Code (The Addison-Wesley Signature Series)

Extreme Programming Explained: Embrace Change (2nd Edition) (The XP Series) Extreme Programming Explained: Embrace Change (2nd Edition) (The XP Series)

Peopleware: Productive Projects and Teams Peopleware: Productive Projects and Teams

The Mythical Man-Month: Essays on Software Engineering, 20th  Anniversary Edition The Mythical Man-Month: Essays on Software Engineering, 20th Anniversary Edition

This is my reading list for Software Engineers. If you haven't read these books, you shouldn't be allowed to program.

Only one of these books, xUnit Test Patterns is new, and could be debated. Its a great book, but its also GIGANTIC. I put it in because it immediately seems to be the authority on how to write unit tests properly and Every developer needs to know how to write unit tests properly. I do think however, that this one will quickly be replaced on the list, but probably with a 2nd edition that covers more dependency injection techniques.

I suppose its also possible that Effective Java could be debated because its language specific, but too bad.

The rest of them are simply not up for debate. If you don't agree, I hope you combust. That said, if you have anything that isn't on this list that really needs to be, please let me know.

There are many, many, many other books that I've read that are not on this list. I'm sure I'm missing some. I reserve the right to come back and adjust it.

Small Goals

Once again I want to try to maintain a list of goals. I fail miserably every time I try - my goals change so rapidly. Here goes:
  • Learn Scala
  • Write an Eclipse refactoring in Scala
  • Contact Dan North to inquire about contributing to JBehave
  • Finish xUnit Test Patterns
Thats going to be it for now. One language, two programming projects, and one book. Usually I'll have several books and a number of other projects, but I think if I stay small I'll do better. However, I really want to put AOP, Spring 2, and Guice up there.

Wednesday, September 05, 2007

Who Should Write Software?

I hesitate to say this, but I really do think that very very few people should be allowed to write software at all. Of the hundreds of developers I've worked with, most of them subtract value from the project. If a developer hasn't read a giant pile of books (which I'll try to list in my next post) then almost every line of code they write is suspect. I've been on some projects with some really smart people, and even they let things deteriorate. Let me try to give some simple examples.

Unit Testing
-- Sometimes even the best people just don't write unit tests. Or, they didn't take a class on unit testing in college, haven't read up on unit testing patterns, and so when they do write unit tests they are dog slow, and become a maintenance nightmare. (I've been personally responsible for this). Developers who don't write tests, or write nightmare tests should NOT be allowed to code until they read more.

Refactoring -- Ordinary developers aren't focused on refactoring. They don't understand that you should strive to remove duplication ALWAYS. They don't understand the right way to do refactorings, or they are scared for a number of reasons. Dev's who add duplication, or haven't read Fowler's Refactoring should NOT be allowed to code.

These are two fundamental ideas in software development, and unfortunately, most developers I've met don't do either. Thats just two. The list goes on and on.

I've read a lot of books on this theoretical list. I can't stop; I'm addicted. Many times after I read a book, especially if I consider it a classic, I say to myself, "I can't believe I ever wrote a line of code before having read that." I realize I've subtracted so much value. Whats worse is it happens all the time. I am a victim of my own high standards here. I should NOT be allowed to write a line of code until I read like 10 more books.

So to finally address the title of this blog, Who should be allowed to write software? What kind of roles should newbies fresh out of college get? How hard to you have to manage developers that haven't read the books on the List? Do you have to monitor their every check-in? Do you have to code review every test? It seems like it to me. But sadly, this would subtract from the time that the best developers have, because someone good is going to have to monitor them. Maybe just lose those people in need of monitoring to free up time for the good people to get it done.

I think it takes 10 years of consistent reading to get to a point where you're always adding value. Thats a huge number. Who should be allowed to write software?