At work, we're getting started on a big rewrite of our main application. In all likelihood, this project will take several people at least a year to complete, as we have to rewrite everything for C# and SQL Server. To put it bluntly, it's time for us to put on our big boys pants and start struttin'.
The boss charged Patrick and I with doing a lot of the architecture work. That excited me; I've never done anything like that on this large of a scale. Also, it meant that the next time I got frustrated with the program structure, I would only have myself to punch in the face. Abuzz with enthusiasm, we hashed it out and talked it over for a few weeks. Finally, after several gajillion emails, we came to an agreement on just about everything. Having reached that point, it was now time to actually get started on the architecture documents to which the entire team would refer. We've got it all figured out, now all we need to do is put it down on paper. That should be the easy part, right? Well, allow me to channel my inner sassy lady and defiantly declare, "NUH UH, HONEY!"
I soon discovered it was nearly impossible to start the damn thing. Hard tasks are like that; there's so much to them, I find it difficult to determine where I should begin. That went on for weeks. Depression set in. I spent all of my time in my office, dressed in black, listening to the Cure. And then, in my darkest hour, my boss came through with a simple set of questions related to the architecture for me to resolve. Starting with those, I'm now back on track.
Here, roughly, are the questions he gave me.
1. Start with a simple physical architecture. How many tiers exist? Where do these tiers exist?
2. Expand the physical architecture into a logical architecture. What are the layers? How do the layers operate and interact with each other?
3. Describe the layers, with regards to encapulation, threads, etc.
Looking back now, I have an idea why these questions motivated me. The way he phrased them, it felt just like a test. The nerd in me knows how important tests are and how critical it is to finish tests in a timely manner, so once I began to think of documenting the architecture in such a fashion, I became much more productive.
The next time I get stuck on a task, I'm going to ask someone to do this for me: come up with a very general, open-ended set of questions that I can attack like a test in order to get me started. Yeah, it's sort of an odd request, but it's certainly preferrable to listening to me singing along to the Cure.
A while back, I wrote about bizarro usability, which is when developers deliberately make something less usable. I said then that I could understand doing this, in light of business concerns. I found another example of this on the ACM Queue website (which always features lots of cool stuff). If you click on any multi-paged article (like this one) and select on printer friendly format, you get the article without all of the junk from the site, but it's only one page at a time. In the forums on the site, someone asked why you didn't get the entire article in printer friendly format and one of the staff members wrote (can't find the link) that's because there'd be no point in buying the magazine if you could view the entire articles like that. When I read that, I immediately began to dance the bizarro usability dance, which features a lot of swivelling, dipping, and unplanned muscle spasms.
However, before I could get too cocky with the concept of bizarro usability, I came across an instance of it that clearly isn't motivated by profitability. In fact, I have absolutely no idea why it was implemented. I suspect the explanation is really, really complicated and would make me want to hit myself in the face with my laptop battery, though.
In the Pragmatic Programmer book, one of the tips they share is to learn a text editor really well. Since these guys are usually spot-on with their stuff, I decided to give this one a shot. As such, I loaded up Emacs, the only text editor capable of flying the space shuttle, and got to torturing myself. After using it for a bit, I realized that I liked Emacs. Even if the key combinations were difficult to remember, the sheer capability of the package impressed me greatly. And then, I went to close the program and I suddenly became very, very confused.
Here's an experiment we can do together. Open up a new, blank file in Emacs and type a character; it doesn't matter what you type. Now, use Control-x Control-c to close the program. At the bottom of the window, Emacs displays a nice little message "Save file /home/cody/newfile? (y, n, !, ., q, C-r or C-h)" Let's ignore the fact that I have absolutely no idea what any of those letters mean except for the first two. We've just been messing around here and we don't want to save anything, so we type n. Emacs still doesn't let us quit; it has yet another message. "Modified buffers exist; exit anyway? (yes or no)", it says. We want to exit anyway, so we type y to exit. And now, the cherry on the cake: Emacs doesn't like that. It bleats, "Please answer yes or no." Unlike the previous prompt, y isn't valid here, WE HAVE TO ACTUALLY TYPE YES.
Huh? What? Why? Do what now?
To me, that entire exiting process is way too complicated. I expect programs to get out of the way when I want to exit, not badger me endlessly until I give them some input that matches their inconsistent prompts. I'm not sure if this bizarro usability or not, though. Without question, it is not usable, but is it deliberately not usable? I can only suspect the answer here is yes. Emacs has been around for 20 years and one must think that at some point, a developer would've become exasperated with this and tried to simplify the exiting process. For whatever reason though, this change never propagated down to the end user.
Considering the organization and the functionality involved, this complication wasn't introduced because to boost profitability. In fact, I have absolutely no idea why that hurdle exists and I can only hope that an Emacs guru can put me on the right track. Whatever the case, I am compelled to think there are times when bizarro usability can be justified and times when it can't. It's justifiable when necessitated by business concerns, as seen with ACM Queue. Maybe there are other situations where it's justifiable also, but it doesn't seem like the Emacs example is one of them.
As bad as it is, I don't plan on looking around in the Emacs source for this code. The stuff contained in there is probably powerful enough to kill me on the spot.
Way back when I was consumed with Cast/Convert fever (more contagious than Disco Fever, less harmful than Yellow Fever), I mentioned there was a difference between the built-in data types in C#. Some are reference types, and others are value types. Java has the same distinction with slightly different verbiage; it possesses reference types and primitive types. As the kids on the street say, what's the dealio?!
To the uninformed, reference type vs. value/primitive type may sound completely made up, like an explanation I'd use whenever someone discovered a crazy bug in my code. Outer voice: "Umm, maybe the method is expecting a ... reference type." Inner voice: "What the hell am I talking about?" But no, these terms actually mean something! And if we're going to be the highly-skilled code ninjas that our business cards purport us to be, we should be able to throw these terms around like nobody's business.
Really, if we just examine the terms, we can get a pretty good idea of what they mean. It may seem shocking, but a value type stores a value of that type. That's so easy, you could almost call it primitive (hey o!). Just to rock your world a little more, a reference type stores a reference that points to the value.
Now that we know the definitions, let's try to deduce what it means. If the value/primitive type is storing the actual value of the variable, then it's got to allocate a specific, appropriately-sized chunk of memory. Knowing that, it'd make sense value/primitive types be very narrowly defined, with a clear range of values. You know, kind of like an int, which is always 32 bits. By cracky, such well-defined numeric values are exactly what we store with a value/primitive type. It's just not numerics that are value/primitive types, but any variable with a specific size (byte, bool, char). It's easy for the compiler to know how much memory to allocate to these types, and it does so accordingly.
What about the sticky wickets? Some types don't have a set size; they possess variable length. Two examples here are strings and arrays. There are no well-defined limits to strings or arrays, they can be however large you'd like them to be plus you can change the size willy-nilly. With that in mind, wouldn't it be a lot more complicated to allocate the m emory for these types? As such, these types are reference types that simply contain pointers to their actual value. And it's not just strings and arrays that are reference types, but any type whose size isn't well-defined. So, classes, interfaces, and delegates are all reference types. If you're ever at a loss to whether something is value/primitive or reference, see if you can make an informed guess as to how large the data type is. If you can't, then it's probably a reference.
Enough with the gum flapping! What does all of this mean? Well, nothing earth shattering, but it adds a lot of wrinkles into coding. For example, a primitive can't hold a null value, while a reference type can. That makes sense: the value type is there to hold a value, while the reference type is merely there to point to something else. In conjunction with this, value types have default values that are filled in by default constructors called whenever you initialize them. Not so with a reference type. Simply put, there's always a value with a value type. If we don't code expecting that, then we could be visited by unpleasant surprises.
It should be no surprise to you that it gets a lot more complex than this. I'm all about keeping it simple here on the vlog though. I do it for two reasons. First, I'm not very intelligent. Second, some of us have better things to do than ramble on the Internet all day, such as catalogue our He-Man plate collection. It's a little complicated, all of this value/primitive/reference type stuff. It's not complicated enough that we should just use strings for everything, though. With some critical thinking and some good online resources, by the power of Greyskull, all of us have the power.
More Reading:
Java Data Types, C# Data Types
In case you need any further proof that I'm an idiot, I read the discussion groups at Joel on Software. Not that the people there are stupid, but online discussion groups in general are stupid, simply because 75% of the messages are "WTF???? YOU USE THE FRAGOMETER 4.27 TO SCRAMBULATE YOUR VECTORMANIONS???? USE 4.27b DUMBASS!!!!!!!!!!" Anyway. I was reading a thread today that was kind of interesting, about writing your apps in a simple scriping language, then writing a converter to translate that simple scripting code into a more robust language. From the first post, I gather that's what Joel's company did with their main product, doing their development in VBScript then converting that to PHP. There are a few advantages here.
1. By selecting an easy scripting language to do your development, you ought to be able to produce a lot of features relatively easily.
2. By translating your scripts to another language, you can accomodate a lot of different environments. If the masses all start running Python instead of PHP, bam, you just change your translator.
3. The people on your team, saving those who do the translator, only have to work in one language with a very easy learning curve. That should make it a lot easier to add new people.
All of these are valid points, yet I can't resist the urge to be a Negative Nancy. Reluctantly I must declare, "Let's scrambulate some vectormanions!"
It seems like for each of these advantages, there exists a disadvantage.
1. With a simple scripting language, you could do a lot of features, but I don't think you could do them well. Simply put, you have less tools at your disposal with which to implement features. As such, the choice is either to simplify the feature or to compensate for your language.
It's easiest to think of this in an analogy. Let's say you take two builders. One has an impressive collection of tools, while the other uses only a hammer and a saw. Which would you want to build a chair for you? I'm sure both could make a sure, but I bet the builder with lots of tools would produce a chair that's a little more refined, and he'd produce it a little bit quicker.
2. You can accomodate a lot of different languages and environments, but only to a shallow extent. That is to say, your production code will always be dumbed down to VBScript's level. You can't add quality or robustness through the translation process, not if it's abstracted. If it's not abstracted, why not just write it in the translated language to begin with?
3. It would be a lot easier to add new people, but can you imagine adding any good people if you only worked with VBScript? "Previously, I was on the team that helped write the OS for the space shuttle. Then, one day I realized I'd be a lot happier writing business apps in VBScript." Unless the CEO has some compromising photos of the developer with a french maid and a jello mold, I don't see that happening.
I've never tried this, so I can't say how effective it'd be. It's certainly an interesting idea, but it's one that would need some more evaluation before jumping right in. All I'm communicating here is that the idea isn't perfect. Now if you'll excuse me, I must go register my disgust with the Fragometer 4.27b.
Brendan apparently pulled himself away from the Keno table long enough to make a good point about UIs; it's not easy to create them with most programming languages. His example was Java. The mere thought of doing a UI in Java makes me want to pound on my desk with my shoe and start wailing like a banshee. Not because it's a bad language or anything, just because of our history together.
Senior year at Trinity, I took a course called Software Engineering. We had to do a semester long project in groups. Half-way through the semester, we switched projects with another team and had to do maintenance on the work they had done. Our original project was really cool; it was a Space Invaders game in C++. The project we had to maintain was decidedly less cool: a LiveJournal client in Java. Being lazy college students, it didn't occur to anyone in our group that it might be a problem that a) all of us were unfamiliar with LiveJournal and b) all of us were unfamiliar with Java.
We realized this the week before all of our changes were due, and half the team promptly quit in abject terror. That left only two of us. The other guy did all of the backend work, while I did the front end stuff in Swing. The Java part came easy enough, but oh sweet Jesus, the Swing part was a little bit tricky. That is to say, I had absolutely no idea what I was doing and did a completely crappy job. In the end, I managed to add one new feature to the UI that crashed almost every time you tried it. In fact, I did such a crappy job, each time you tried to use the LJ client, the computer desk burst into flames. I would've been worried about this, had I not been so exasperated with Swing. It came through when it counted, though; for reasons I;ll never be able to explain, the UI worked beautifully when we had to present. Sometimes, it's better to be lucky than good.
Are there any UI-friendly languages? Well, I can think of two: VB and Tcl/Tk. And, oddly enough, many agree that neither of these are industrial-strength programming languages. Why is that? Is there some sort of trade-off between ease of front-end creation and programmability (made up term, but I like it)? I have no idea, and I'm not versed in enough languages to really comment here. But I do know that every time I think of doing another front end in Java, I have a hard time holding back the tears.
Just a teensy little bit more about casting and converting with C#. Previously, we covered the relative strengths and weaknesses of both methods for converting types in C#. Now let's be honest here: after the last post, it was freaking impossible not to get swept away in a moment of fancy and think to yourself, "Maaan, it'd be great if there was some way to combine casting and converting!" And then, maybe you went overboard on the moment of fancy and thought, "If this software thing doesn't work out, I'm going to start up a diner full of Andy Griffin memorabilia! We'll get Don Knotts for the ribbon cutting!" Both thoughts are equally intriguing, but only one is appropriate for the vlog (my apologies to Mr. Knotts).
As savvy programmers, What'd we like is a method that combines the speed and ease of casting with the flexibility of converting. Luckily, the C# fairies sprinkled just enough pixiedust on the compiler to acommodate this, sort of. The magic word here is 'as'.
Let us code with the futzy old method! (Apologies to America's favorite portly funny man.)
string domCalories = (string) domDeLuiseBreakfast;
MessageBox.Show(domCalories);
}
catch(Exception ex)
{
MessageBox.Show("Oops! " + ex.Message);
}
Welcome to exception city, population you. We can get around this with a sneaky part of C#, the "as" keyword. Take a whiff of this.
//we're not casting, we're using the as keyword.
string domCalories = domDeLuiseBreakfast as string;
MessageBox.Show(domCalories);
}
catch(Exception ex)
{
MessageBox.Show("Oops! " + ex.Message);
}
So 'as' returns null for invalid casts, instead of throwing exceptions. Hoorah, we'll use that from now on and never again use cast or convert. Not so fast, hot shot. Let's alter our code sample slightly. domCalories is an int now instead of a string.
//no longer as string,now as Int16.
int domCalories = domDeLuiseBreakfast as Int16;
MessageBox.Show(domCalories.ToString());
}
catch(Exception ex)
{
MessageBox.Show("Oops! " + ex.Message);
}
Summing up the past couple of entries, we now have three separate cases for casting, using 'as', and converting.
Why it's so easy, you could teach it to a squirrel. It's possible to make it much more complicated than all of this, but our jobs are complicated enough already. For that reason, I'm a strong proponent for keeping it simple. With a few simple rules of thumb, you can tackle almost any variable conversion situation in C#. Not only that, but it gives you the valuable opportunity to give something back to the squirrel programmer population.
Here's a joke I just made up about casting. Yes, I am a horrendous nerd.
One day, an integer was walking down the street when he spied a man in a booth. Above the booth, a sign read, "I'll Make You a Long for $1!" Always wanting to be a float, the integer ran over to the man and gave him a big pile of money. In return, the man gave him a magic pill that he promised would turn the int to a long.
That night, the int took the magic pill. He immediately felt bigger, but he wasn't sure just how much bigger he was. He decided to test it out by assigning himself the lowest number he could think of, -3,000,000,000,000,000,000. Immediately when he tried, he broke to pieces. An ambulance came immediately and took him to the hospital, where only a team of sophisticated type surgeons could piece him back together.
The next day, the man who sold him the pill came to visit. Hysterical, the man said, "Oh God, it's all my fault! Is there anything I can do?" Cool as a cucumber, "Actually, yes. How about you sign my cast?"
HA HA HA HA, ohhhh my sides!
Now that we've identified what cast and convert are used for in C#, let's do a little detective work to determine how these two actually work. In doing detective work, it's always helpful to assume the persona of a famous private investigator, so imagine me typing all of this while dressed like Magnum PI.
The simplest way to illustrate the difference between casting and converting is with a code sample. Consider the following example of casting a string into an int, a hopeless task in this situation.
Let's review our results. We tried to do an invalid cast, and the compiler caught it, sending us back to our mommas. We tried to an invalid convert, and the compiler allowed it. Running the program then raised an exception that we were able to handle. From this, we can determine that casts are a lot stricter in what they'll handle than the comparatively lenient methods of the Convert class. In addition to that, a failed cast has a worse impact on the program than a failed convert.
What's the conclusion? Well, if casts are much stricter and more devastating upon failure, then we should only use them when we can guarantee success. Casts are only appropriate for data internal to the program, where validity can be ensured. Converts, being more flexible, are appropriate for other things where failure is a possibility, like handling input from a database or a user.
Unfortunately, casts are supposedly faster than converts (I'd like to see some numbers here), so we can't get rid of them entirely. Instead, we must eye them warily, like a farmer who's taken in a travelling salesman. Our user/db input is like our fetching daughter, who must be guarded zealously from this brute. If, in the dead of the night, we hear the salesman getting close to the daughter, it's our job to run towards the barn, screaming like holy hell and brandishing a pitchfork. A programmer's job is never done.
Okay, enough with pseudo-nerdery; it's time to get wonky. Specifically, I'd like to write today about the differences between casting and converting in C#. Developers (and Microsoft in the documentation) use these terms interchangeably, but they're quite different. Such confusion causes pedantic jerks around the world (like me) to hyperventilate and break out in hives. We must put our foot down regarding these concepts, and to borrow a quote from Animal House, that foot is me.
As a language, C# is strongly-typed. A lot of ambiguity surrounds this term, but basically it means all variables must be declared with a type, and each variable must adhere to its type. That last part just means that if you declare something as a string, you're not allowed to suddenly treat it like an integer and add 15 to it. As a result, strongly typed languages enforce consistency, and that's a good thing. Okay, most programmers know this already.
In almost any non-trivial program, a developer will encounter a situation where she needs to use the data from a variable in an altogether different context. For example, say you've declared a variable x as a double, and you're using x to track the number of dollars your department has spent on Garfield posters (trust me, any reasonable organization will need a double to track this amount). At the end of each week, you're supposed to tell your boss the grand total. However, she's not really interested in the complete amount; she just wants it rounded down to the nearest dollar. It's clear here that what you need to do is change that double, which tracks dollars and cents, to an int, which doesn't carry decimal places. How do we go about that in C#?
Well, maybe like this:
Casting and converting are the two main ways to change types of a variable (there are other methods too, and we'll get to them eventually). Casting looks like this:
As you can see, I'm kicked my unhealthy obsession with OO for an equally unhealthy obsession with UML. I just can't help myself! I woke up this morning and heard a booming voice bellow, "Let it be usable!" At first, I thought it was a sign from above, but it turned out to be my neighbor screwing around with his PA system. Once I discovered that, I considered disregarding the whole usability thing, but do I really want to get on the bad side of a neighbor with a PA system? Hell no.
Usability, according to the folks at dictionary.com, is the effectiveness, efficiency, and satisfaction with which users can achieve tasks in a particular environment of a product. In all honesty, I don't even see the point for the word when the definition just rolls off your tongue like that. Recently, in my travels across the web, I began to think about the consequences of usability. It might not shock anyone, but usability is a trade-off. That should be evident to any UI developer; that which is usable is not always that which is easy to code. Sometimes, you have to sacrifice simplicity of code for usability. That's an obvious usability trade-off, but are there any others that are more subtle? You bet your sweet bippy.
Like a lot of folks, my web usage at work is monitoring through the use of a proxy server. We have a certain amount of discretionary browsing time we can use each day, and this time is triggered whenever we visit certain sites. No, by certain sites, I'm not referring to naked lady sites, but to entertainment, sports, and shopping sites. Okay, fine, whatever: none of my coworkers are excited by this, but it's manageable.
One of these certain sites is theonion.com. They've been doing great stuff for years, and a Wednesday ritual of mine is to check out the new issue. Part of their site is the Onion AV Club, where they review movies, music, and books. I stop by there every week too. A couple of weeks ago, I noticed something sinister on the review pages: the reviews were now broken up, so that each had its own individual page (and thus its own set of ads). This makes it even more difficult to view this part of the site, because those of us whose browsing is monitored now must use up even more of our discretionary browsing time. Certainly the people at the Onion aren't as nefarious as Lex Luther or Dr. Evil, but the new arrangement does make it harder to view the site for some of us. In taking a step backwards, the Onion ostensibly engaged in Bizarro Usability.
Making this decision, the folks at the Onion had to decide between advertising revenue and optimum usability. I'd wager this is a common dilemma for popular websites (clearly, I'd have no idea). In a business setting, one can't mindlessly beat the drum for usability; business needs must enter into the calculus also. Occasionally, these business needs will necessitate the use of some bizarro usability of our own. To me, there's nothing wrong with this, as it's this very same revenue that keeps me from tapdancing for change down on the corner. Usability is a great goal, but because of inherent trade-offs like this, it can't be pursued recklessly. Now if you'll excuse me, I need to find a place to rent a PA system.
At work, I'm primarily a User Interface developer. That means, instead of working with cool stuff like algorithms and databases and murderous cyborgs, I spend my days trying to make buttons do the right things. Some don't care for that type of programming, but I do; I find it gratifying to watch something I made work on the screen. I don't know many other UI programmers, but I suspect that if I did, we'd go out to bars en masse occasionally. At these bars, we'd huddle together over appletinis and artichoke dip, and we'd tell war stories. "I once got my multi-threading so screwed up, my computer exploded and singed all my toe hair off!" We'd laugh and slap each other on the backs, but not too heartily, for we are delicate programmers. It sounds like a night of revelry to me.
Then, as our outing began to wind down, someone in the group would whisper, "What about usability?" Everything would stop, like a scene from a western where a stranger strides into a bar and declares, "I'm looking for the man who shot my pa, Grizzly Bear Bill!" We'd all stare at the floor and shrug uncomfortably, because usability is scary.
Why scary? Well, usability is a nebulous field. Sure, academics try to apply all sorts of metrics to it, but they can't obscure that the concept of usable isn't universally agreed upon. There are some guidelines that you kind of work with, but it's a lot more like alchemy than chemistry: all you can do is to try your best and hope you don't blow yourself up in the process.
As such, usability isn't really the domain of programmers. Part of the reason I like programming is because it eschews any notion of ambiguity; the bit is either there, or it isn't. Usability is completely orthogonal to that concept. You can't lump screens into usable and not usable, but shuffle them around into a million fuzzy categories on which no one can agree. It requires an entirely different frame of mind from programming, where the focus isn't on correctness, but on acceptability. I find it frustrating to shift between the two mindsets, and I suspect other UI programmers could agree.
If anything, usability seems like a more appropriate duty for the folks on the other side of the hall: people who live to make Word documents and Powerpoint presentations. As I see it, analysts and program managers exist to simplify things. They carve off little bits of the program and present them to us in easy-to-swallow paragraph form. They focus entirely on how software should work, not how it is actually implemented. To me, that makes them the true usability experts.
Okay, so the analysts/PMs are usability experts; that doesn't mean the burden of usability is suddenly lifted from the shoulders of us UI guys. What it DOES mean is that we, as UI programmers, have a very valuable resource within shoe-throwing distance. The next time you're starting to get exasperated about usability, don't go to the coder sitting next to you for answer. Go to the guy in the snazzy pants who has Clippy prominently featured on his desktop. By going to those with better answers, we can't simplify the concept usability, but we can simplify the way we approach it. That leaves us more time for the important stuff, like coding and appletini binges.
As you may've noticed, I think a lot about object oriented design lately. It's gotten so bad, I now cover my walls with pictures of Martin Fowler, like a 10 year old girl in 1988 with her Corey Haim posters. Not really. Well, just a little bit, but I promise he's wearing a shirt in all of the pictures.
In musing over OO, I'm beginning to see how aspects of object oriented design are all around us every day. For proof of this, go a grocery store. Once there, you'll see a lot of people, all focusing on different things. Some are working cash registers, others are pushing the carts around the parking lot, while others still are stacking up rudabegas in the produce section. Imagine if you went up to one the cart guys in the lot with a can of vienna sausages and a dollar, and told him you'd like to make a purchase. Would he commit the transaction? Of course not. He'd tell you to go back inside to see the cashiers, and then he'd whisper into his walkie talkie, "Security, we've got a Vienna Sausage incident in the making."
The same would happen with any of these workers if you went up to them and asked for help in an area that isn't their duty; rather than help you directly, they'd direct you to the right person. From a personal standpoint, I've never been into a supermarket and seen a bunch of employees, each carrying a mop, a cash register, and a big cart full of products to shelve. No sir, they separate those tasks so each person can devote their energies to one main task. As a result, the work force is decentralized, segmented, and hyperfocused, a lot like we expect our objects to be when programming. In economics, we call this division of labor.
In all of the pictures I've seen of Adam Smith, the grandaddy of microeconomics, I've never seen him wearing a shirt that said, "There are only 10 kinds of people on earth: those that understand binary and those that don't." That's a shame, because Adam Smith thought like a programmer. Take a look at this passage from his seminal work, the Wealth of Nations, where he first introduces the concept of division of labor.
"To take an example, therefore, from a very trifling manufacture; but one in which the division of labour has been very often taken notice of, the trade of the pin-maker; a workman not educated to this business ... could scarce ... make one pin in a day, and certainly could not make twenty. But in the way in which this business is now carried on, ... it is divided into a number of branches, of which the greater part are likewise peculiar trades. One man draws out the wire, another straights it, a third cuts it, a fourth points it, a fifth grinds it at the top for receiving the head; to make the head requires two or three distinct operations; to put it on, is a peculiar business, to whiten the pins is another; it is even a trade by itself to put them into the paper; and the important business of making a pin is, in this manner, divided into about eighteen distinct operations, which, in some manufactories, are all performed by distinct hands, though in others the same man will sometimes perform two or three of them."
"I have seen a small manufactory of this kind where ten men only were employed, ... they could, when they exerted themselves, make among them ... forty-eight thousand pins in a day. Each person, therefore, making a tenth part of forty-eight thousand pins, might be considered as making four thousand eight hundred pins in a day. But if they had all wrought separately and independently, and without any of them having been educated to this peculiar business, they certainly could not each of them have made twenty, perhaps not one pin in a day."