<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-35812529</id><updated>2011-12-14T19:01:16.623-08:00</updated><title type='text'>programming_tips</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://programming-trics.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35812529/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://programming-trics.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>programming_tips</name><uri>http://www.blogger.com/profile/16707691078734857581</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-35812529.post-116050760470627488</id><published>2006-10-10T12:12:00.000-07:00</published><updated>2006-10-10T12:13:24.713-07:00</updated><title type='text'>Writing Cross-Platform Software</title><content type='html'>&lt;h2&gt;&lt;a name="AEN19" class="anchor"&gt;Why cross platform?&lt;br /&gt;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;       You might wonder what the point of reading an article on cross-platform       development is.   Do you program for Linux?         Why would we want software on any platform but Linux?        There are lots of reasons to write cross-platform code.     &lt;/p&gt;   &lt;p&gt;       Cross-platform development can mean different things. Jon Watte of Be, Inc.       says that "Portable, to some people, means it builds on at least two Linux       distributions with various flavors of gcc." It is a spectrum that        ranges from porting crusty old legacy code that can only build on one version        of a particular compiler and run on one platform to porting an application        between different major platforms, to simultaneous cross-platform development        by coding to a platform-independent application framework.     &lt;/p&gt;&lt;p&gt;       Java is not really a cross-platform development environment; it is a platform       in itself (this is also        &lt;a href="http://www.research.att.com/%7Ebs/bs_faq.html#Java" target="_top"&gt;pointed out  by Bjarne Stroustrup&lt;/a&gt;, which is readily able to run on almost       any machine, but one in        which platform specific features can be used only with great difficulty.  It        is my intention to focus on cross-platform development in C and C++, although        I expect I will have more favorable things to say about Java later.     &lt;/p&gt;&lt;p&gt;       It would be especially helpful to increase the acceptance of free software if       users could run their applications on any platform they wanted and exchange       documents with users on other platforms, as is possible with the AbiWord word       processor from &lt;a href="http://www.abisource.com/" target="_top"&gt;AbiSource&lt;/a&gt;,        which presently runs on Linux and other Unix       variants, BeOS, and Windows, with MacOS and QNX versions in development. It       is less likely that a whole company will adopt Linux than that a few geeks       and power users will bring the OS in because of their personal preference; if       they can be integrated into the company productivity system without need for        clumsy and inaccurate file format translators then Linux will have greater        acceptance, and ultimately less technical users will adopt Linux because of        its many advantages.     &lt;/p&gt;&lt;p&gt;       With Linux starting to make inroads on the desktop, publishers of applications       for Windows and MacOS are increasingly interested in shipping Linux versions        of their products - for some it is a major strategic decision made to compete        with Microsoft, as with Corel's WordPerfect. It can be pretty painful to        perform such a port, but it can be done. Spellswell from        &lt;a href="http://www.working.com/" target="_top"&gt;Working   Software&lt;/a&gt; is one of the earliest Macintosh applications that is still        shipping (it was written on the 512k Mac with floppies and no hard drives,        then later ramdisks, and spellchecked Word 1.0 documents), and was full of        non-portable code, but I ported it to the BeOS and the OEM version is also        available on Windows.     &lt;/p&gt;&lt;p&gt;       Why port? Besides the obvious benefit of your program running on more than        one kind of computer, &lt;span class="emphasis"&gt;&lt;i class="emphasis"&gt;porting is good for code&lt;/i&gt;&lt;/span&gt;. The work        required to        make a single set of sources work for more than one platform increases its        robustness, makes maintenance easier and improves the reusability of your        code. Exposing your code to multiple compilers reveals coding errors in one        compiler that are not detected in another.     &lt;/p&gt;&lt;p&gt;       For example, I did simultaneous development of a MacOS and        Windows application using a cross-platform framework named        &lt;a href="http://zoolib.sourceforge.net/" target="_top"&gt;ZooLib&lt;/a&gt; written       by my friend Andy Green (more about it in a future column).  I used the        &lt;a href="http://www.metrowerks.com/" target="_top"&gt;Metrowerks&lt;/a&gt; CodeWarrior Pro        compiler, which runs on Mac and Windows.  Various incarnations of the        MetroWerks C++ compilers can build applications for:     &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;680x0 and PowerPC MacOS&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pentium Windows&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;PalmOS&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;QNX Neutrino with x86 and PowerPC&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Nucleus PLUS with PowerPC, MIPS and NEC V8xx&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;PowerPC BeOS&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Game consoles&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;       It also supports Java development and the IDE can be used to drive gcc on        Linux, Solaris and BeOS. Interestingly, MetroWerks publishes PowerPlant, the        most popular application framework on the MacOS, but it is highly        Mac-specific and shows no signs ever having cross-platform support -        CodeWarrior for Windows supports Microsoft Foundation Classes.     &lt;/p&gt;&lt;p&gt;       I have found several code constructs which will build on Windows but not even        compile on PowerPC, or work fine on PowerPC but not 68000 - sometimes due to        my bug, sometimes due to a bug in the compiler. There is a benefit to the        community in writing cross-platform code, in that it helps the compiler        programmers improve their products if application developers report bugs they        find in the development tools.     &lt;/p&gt;&lt;p&gt;       When &lt;a href="http://www.be.com/" target="_top"&gt;Be, Inc.&lt;/a&gt; switched from building        the BeOS on Pentiums with        CodeWarrior to gcc, they found many instances of code that would build       under one compiler but not the other, allowing them to improve the quality of        their code.  Us BeOS developers had the same experience building our        applications. Even though Apple stopped providing low-level specifications to        their new motherboards, so Be could no longer implement support for new models of        Macintoshes, Be continued to develop and support PowerPC Macintoshes because        it helped proof the Pentium code and uncover bugs in newly written code, and        helped maintain the portability of the system.     &lt;/p&gt;&lt;p&gt;       Testing your application on different platform will ease debugging. Latent or        unreproducible bugs on one platform often will become readily reproducible on        another because of the different environment or layout of memory. Also you        may be able to take advantage of platform-specific memory debugging tools        such as &lt;a href="http://www.onyx-tech.com/products/spotlight.html" target="_top"&gt;  SpotLight&lt;/a&gt;,        &lt;a href="http://www.compuware.com/products/numega/dps/vc/bounds.htm" target="_top"&gt;  BoundsChecker&lt;/a&gt;,        &lt;a href="http://www.gnu.org/software/gcc/projects/bp/main.html" target="_top"&gt;Bounded  Pointers for GCC&lt;/a&gt; or        &lt;a href="http://www.rational.com/products/pqc/index.jsp" target="_top"&gt;Purify&lt;/a&gt; and find bugs in code running on        one platform that could affect all platforms.     &lt;/p&gt;&lt;p&gt;       Even if you only write code for Linux, it is to your benefit to aim for        cross-platform compatibility.  Besides building on Pentium with gcc, you        could build gcc as a PowerPC or Alpha cross-compiler and have a friend test        your binaries - or invest in a second machine with a different processor        architecture for testing.  For the best results, obtain a second,        independently developed compiler that builds for your main development        machine and build and test your code with that compiler periodically. I        dislike like using Microsoft Visual C++ because of the MDI interface but test       my Windows projects with it to do such verification.     &lt;/p&gt;&lt;p&gt;       If you work on a collaborative project, try to find at least one member for        your team who writes on a platform with a different byte order.  If you are        on a programming team at a company, your programming team should be outfitted        with at least one machine with a different byte order that is used in regular        day-to-day development, and preferably there will be at least as many        processor architectures as team members.     &lt;/p&gt;&lt;p&gt;       Even if you only desire your code to run on a Unix variant, there are many        different processor architectures and compilers in use.  You need to        architect your code so that byte-order dependencies are handled properly, and        you have to handle the processing of file and network data so that there is        no dependency on processor or compiler dependent structure alignment.     &lt;/p&gt;&lt;p&gt;       Some cross-platform frameworks provide least-common denominator behaviour.         An application cannot take advantage of special features of the platform it        is running on - or have distinctive behaviour that is expected by users of        particular platforms. For example, the javax.comm serial communications        package for Java provided by Sun provides a method for enumerating the port        names so they can be presented to the user for selection.       &lt;/p&gt;&lt;p&gt;       On a Windows machine the enumeration returns "COM1:" and "COM2:", and on a        Mac the result is "Modem Port" and "Printer Port."  But there was no        provision in the javax.comm API for port icons; Macintosh serial ports are not        labeled on the machine case with text - they have icons showing a telephone        handset and a printer.  A Java program will look out of place on the MacOS        when compared to native Mac programs because it doesn't have the icons that        are normally used for port selection.      &lt;/p&gt;&lt;p&gt;       Mac applications also have a menu bar across the top of the screen and        usually do not have one in the document window, while most other platforms        provide the menu bar in the document window. It is common for Windows        applications to use the "Multiple Document Interface" in which document        windows slide around inside a containing application window - the MDI        interface generally causes a violent reaction to people who prefer other        platforms; I would be completely unwilling to write Windows software if the        development environments I use did not give me a choice between interface        styles. It is important to support the native interface on the platform your        application is running on.     &lt;/p&gt;&lt;p&gt;       This least common denominator approach is not necessary and I feel is wrong.         I believe it is fully possible to write cross-platform code that has behaviour        unique to each platform, and that takes advantage of special capabilities where       they are available.     &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35812529-116050760470627488?l=programming-trics.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming-trics.blogspot.com/feeds/116050760470627488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35812529&amp;postID=116050760470627488' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35812529/posts/default/116050760470627488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35812529/posts/default/116050760470627488'/><link rel='alternate' type='text/html' href='http://programming-trics.blogspot.com/2006/10/writing-cross-platform-software.html' title='Writing Cross-Platform Software'/><author><name>programming_tips</name><uri>http://www.blogger.com/profile/16707691078734857581</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35812529.post-116050754044552206</id><published>2006-10-10T12:10:00.000-07:00</published><updated>2006-10-10T12:12:20.486-07:00</updated><title type='text'>5 Principles For Programming</title><content type='html'>Here are a few things I have learned about programming computers, in no particular order. I didn’t invent any of them, and I don’t always follow them. But since nobody seems to know very much about making good software, it makes sense to try to distill a little wisdom when possible.&lt;div class="post-entry"&gt; &lt;p&gt;&lt;strong&gt;Fail Fast&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Check for programming errors early and often, and report them in a suitably dramatic way. Errors get more expensive to fix as the development process progresses–an error that the programmer catches in her own testing is far cheaper then one the QA tester finds, which is in turn far cheaper than the one your largest customer calls to complain about. The reason this matters is that the cost of software comes almost entirely from the errors. To understand why this is, consider writing code in the following manner: you are assigned some feature, you type up a complete implementation all in one go, then you hit compile for the first time. (I TA’d a beginning programming class in grad school and this is not very different from how beginning programmers insist on working.) The point is that if you have any experience writing software you know that if getting to the first compile required n man-hours, then the time required to having shippable code is probably between 2n and 100n man-hours, depending on the domain. That time will be divided between the programmer’s own bootstrap testing, QA time (and the associated bug fixing), and perhaps some kind of beta.&lt;/p&gt; &lt;p&gt;The classic examples of this principle are type-checking, unit testing, and the assert statement. When I first learned about the assert statement I couldn’t accept that it was useful–after all, the worst thing that can happen is that your code can crash, right? and that is what the assert statement causes. For all the hoopla about unit testing, you would think that it was something deeper then just a convention for where to put your assert statements. But software development is in such an infantile stage, that we shouldn’t poke fun–unit testing, for all the child-like glee of its proponents–may well be the software engineering innovation of the decade.&lt;/p&gt; &lt;p&gt;You see the violation of the fail fast principle all the time in Java programming where beginning programmers will catch (and perhaps log) exceptions and return some totally made up value like -1 or null to indicate failure. They think they are preventing failures (after all whenever an exception shows up in the logs it is a problem, right?) when really they are removing simple failures and inserting subtle time-sucking bugs.&lt;/p&gt; &lt;p&gt;Unfortunately the idea of failing fast is counter-intuitive. People hate the immediate cause of pain not the underlying cause. Maybe this is why you hear so many people say they hate dentists, and so few say they hate, I don’t know, plaque. This is a lot of what irritates people about statically typed languages–when the compiler complains we hate the compiler, when the program does what we say and crashes we hate ourselves for screwing up–even when it is an error that could have been discovered by a more vigilant compiler.&lt;/p&gt; &lt;p&gt;This is why I can’t work myself into the same first-kiss level of ecstasy others manage over languages like Ruby[1]. Dynamic code feels great to program in. After the first day you have half the system built. I did a huge portion of my thesis work in Python and it was a life saver. Thesis work doesn’t need to be bug free, it is the quintessential proof-of-concept (and yet so many CS students, when faced with a problem, break out the C++). But I have also worked on a large, multi-programmer, multi-year project, and this was not so pleasent. A large dynamically typed code base exhibits all the problems you would expect: interfaces are poorly documented and ever changing, uncommon code paths produce errors that would be caught by type checking, and IDE support is weak. The saving grace is that one person can do so much more in Python or Ruby that maybe you can turn your 10 programmer program into three one programmer programs and win out big, but this isn’t possible in a lot of domains.  It is odd that evangelists for dynamic languages (many of whom have never worked on a large, dynamically-typed project) seem to want to deny that static type-checking finds errors, rather than just saying that type-checking isn’t worth the trouble when you are writing code trapped between a dynamically typed database interface and a string-only web interface.&lt;br /&gt;Syntax highlighting (and auto-compilation) in IDEs is another example of this principle, but on a much shorter timescale. Once you have become accustomed to having your errors revealed instantaneously it is painful to switch back to having to wait for a compiler to print them out in bulk one at a time.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Write Less Code (and Don’t Repeat Yourself)&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This is perhaps the most important and deep principle in software engineering, and many lesser principles can be derived from it. Somehow simple statements/programs/explanations/models are more likely to be correct. No one knows why this is; perhaps it is some deep fact about the universe, but it seems to be true.&lt;/p&gt; &lt;p&gt;In software this comes into play as bugs: longer programs have a lot more bugs so longer programs cost more.&lt;/p&gt; &lt;p&gt;Worse, difficulty seems to scale super-linearly as a function of lines of code. In the transition from Windows XP to Vista the codebase went from 40 million to 50 million lines of code. &lt;a href="http://blogs.msdn.com/philipsu/archive/2006/06/14/631438.aspx"&gt;To do this took 2,000 of the world’s best software engineers 5 years of work&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The reason for this is that the only way to get real decreases in program size (decreases of more than a few characters or lines) is to exploit symmetry in the problem you are solving. Inheritance is a way to exploit symmetry by creating type hierarchies, design patterns are an attempt to exploit symmetry of solution type. Functional languages are still the king of symmetry (all of lisp is built out of a few primitive functions). But rather than categorize these by the &lt;em&gt;mechanism&lt;/em&gt; of the solution, it is better to think of them as what they are: ways to write less code.&lt;/p&gt; &lt;p&gt;The best way of all to avoid writing code is to use high quality libraries. The next time you find yourself writing a web application reflect on how little of the code executing is really yours, and how much belongs to the Linux kernel, Internet Explorer, the Windows XP, Oracle, Java, and the vast arrays of libraries you rely on (”ahh the old hibernate/spring/JSF/MySQL solution, so lightweight…”).&lt;/p&gt; &lt;p&gt;Some of the difficulties of large programs are technical but many are sociopolitical. Microsoft is the size of a medium sized country by income and the size of at least a small city by head-count. Yet it is run in much the same way as any 200 person company, namely some guy tells some other guy what to do, and he tells you. Unfortunately they have found that none of these things work at that scale, and I don’t think anyone has a really good idea of how to fix them.&lt;/p&gt; &lt;p&gt;Your problem doesn’t require a small city to produce, but the principle is the same. If your solution requires double the man-power then all the organizational overhead will have to be developed to handle this. Furthermore the organization will be composed of computer programmers who are often at roughly the same level of interpersonal sophistication as &lt;a href="http://images.google.com/images?hl=en&amp;q=sling%20blade"&gt;that sling blade guy&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;What is remarkable, though, is that to make the solution small means also making it clear. I think that this has mostly to do with human brains. We can only think one or maybe two sentences worth of thought at a time, so finding the concepts that make your solution one sentence is essential. The famous &lt;a href="http://www.haskell.org/haskellwiki/Introduction#Quicksort_in_Haskell"&gt;haskell quicksort&lt;/a&gt; is a perfect example of this. I can’t help but feel jealous of the computer science students ten years from now who will see algorithms presented in that way. (If you don’t read haskell the program just says: “An empty list is quicksorted. The quicksort of a non-empty list is the concatenation of (1) the quicksort of list elements less than the first element, (2) the first element itself, and (3) and the quicksort of list elements greater than the first element.” Though, of course, the haskell version is much briefer.)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Computer Programs Are For People&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;“We want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.”&lt;/em&gt;&lt;br /&gt;&lt;a title="sicp" href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt; The Structure and Interpretation of Computer Programs&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The wonderful thing about the above quote is that it gets less brave and more obvious every year. We know that c/java/lisp/haskell have not one bit of power that isn’t in simple assembly langauge–they only allow us to express the ideas more clearly and prevent certain kinds of stupid mistakes. There is no program that can be written in one that can’t be written in another, and all end up as machine instructions sooner or later (some at compile time, some at run time, but no matter). Given this fact it should be obvious that the only reason to have a programming language is to communicate to a person. Don Knuth wrote about this idea, calling it Literate Programming, and created a system called WEB which was a great idea mired in a terrible implementation[2]. The idea was to embed the program in an essay about the program that explained how it worked. The Sun programmers simplified this in some ways with Javadoc, but still something was lost, since it is very hard to get any of the big ideas out of Javadoc, or even to know where to start reading. Projects always have two links: one for Javadoc and one for a higher level documentation which is written in some other system. WEB created a linear narrative to describe a program that might not be quite so straight-forward; Javadoc creates a flat list of documentation with no beginning, end, or summary. Neither is quite what I want.&lt;/p&gt; &lt;p&gt;It is a small tragedy that programmers who spend so much time trying to understand obscure code, and so much time creating new lanauges to write more obscure code in, spend so little time coming up with the WYSIWYG version of WEB that makes program source input look like the beautiful WEB/TEX output.&lt;/p&gt; &lt;p&gt;I think the best ideas in object-oriented programming also fall under this category. The methodology of solving a problem by creating a domain model to express your problem in is the best example. The point of such a model is to create that level of abstraction which exists wholly for people to think in. Not all problems are easily broken by such a method but many are. The concept of encapsulation (you know, the reason you type private in front of all those java variables) is another example. Both of these are to make things simpler, more usable, to put it simply, more human.&lt;/p&gt; &lt;p&gt;A sort of corollary of writing computer programs for people, writing less code, and solving the general problem is the following: write short functions. If I could transmit only a single sentence to the programmers of tomorrow which summed up everything I knew it would be that: write short functions[3]. When you write short functions you are forced to break the code into logical divisions and you create a natural vocabulary built out of function names. This makes the code an easily readable, easily testable, set of operations. When you have done this it becomes possible to see the duplication in your code and you start solving the more general problems. It is sad that the best piece of software engineering advice that I know of is to write short functions, but, well, there it is. Don’t spend it all in one place.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Do The Right Thing&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This principle sounds funny when stated directly, after all who is advocating doing the wrong thing? And what is the right thing to do, anyway?&lt;/p&gt; &lt;p&gt;The point is that in the process of developing software I am always facing the following situation: I can cut corners now, hack my way around a bug, add another special case, etc. OR I can try to do the right thing. Often I don’t know what the right thing is, and then I don’t have a choice but to guess. But more often, I know the best solution but it requires changing things. In my experience every single factor in the software development process will argue for doing the wrong thing: schedules, managers, coworkers, and even, when they get involved, customers. All of these groups want things working as soon as possible, and they don’t care what is done to accomplish that. But no one can see the trade-off being made except for the programmers working on the code.  And each of these hacks seems to come back like the ghost of Christmas past in the form of P0 bugs, and I end up doing the right thing then under great pressure and at higher cost then I would have done it before.&lt;/p&gt; &lt;p&gt;A lot of times doing the right thing means solving the more general problem. And it is an odd experience in computer programming that often solving the more general problem is no harder then solving the special cases once you can see the general problem.&lt;br /&gt;There is a lot of advice that argues the opposite. This line of thought says just throw something out there, then see how it is conceptually broken, then fix it. This argument is perfectly summarized in the “&lt;a href="http://www.jwz.org/doc/worse-is-better.html"&gt;worse-is-better&lt;/a&gt;” discussion, and I don’t have much to add to it. Except to say this, I think that worse-is-better is a payment scheme. With worse-is-better you get 85% of a solution for dirt cheap, and the remaining 15% you will pay in full every month for the rest of your software system’s life. If you are writing software that you know will be of no use tomorrow, then worse-is-better is a steal, (but you might want to consider quitting your job). If you are writing software that will last a while you should do the right thing.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Reduce State&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;You may have heard that &lt;a href="http://en.wikipedia.org/wiki/Amdahl%27s_law"&gt;Amdahl’s law&lt;/a&gt; is the new &lt;a href="http://en.wikipedia.org/wiki/Moore%27s_law"&gt;Moore’s law&lt;/a&gt; and that by the time Microsoft finishes the next version of Windows computers will have like &lt;a href="http://news.com.com/Intel+pledges+80+cores+in+five+years/2100-1006_3-6119618.html"&gt;holly shit 80 fucking cores&lt;/a&gt;. This means that in five years when your single threaded program is going full tilt boogie it will be using all of 1/80th of the processor on the machine. As a semi-recent computer science grad. student my opinion of concurrency is “neato.” But I notice the old timers at work have more of a “we are so totally fucked” look about them when they talk about it. I think the reason for this is this: if x is a mutable object then the following doesn’t hold in multithreaded program:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;x.equals(x)&lt;br /&gt;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;Like everyone else, I am guessing that the end game for all this will be a massive reduction in mutable state. Those functional language people are definitely on to something. But those of us who still have to program in &lt;a href="http://java.sun.com/"&gt;dysfunctional&lt;/a&gt; languages during the day need a more gradual path. The question is, if mutable state is bad, is less mutable state less bad? or do I have to get rid of it all?&lt;/p&gt; &lt;p&gt;I don’t know the answer to this. But for a while now, I have been trying the following. Whenever possible avoid class variables that aren’t declared &lt;code&gt;final&lt;/code&gt;. See functional programming gets rid of side-effects altogether, but I know if this is necessary.  Inside a function the occasional &lt;code&gt;i++&lt;/code&gt; really isn’t that confusing and I am not sure I want to give it up just yet. The reason is that method-local variables have no publicly accessible state, so as long as I am writing short functions this temporary state shouldn’t be a problem. By declaring &lt;code&gt;x&lt;/code&gt; &lt;code&gt;final&lt;/code&gt; you ensure that &lt;code&gt;x.equals(x)&lt;/code&gt;. This also makes it very easy to prevent invalid states, just ensure that either the user provides valid inputs to the constructor or the constructor throws an exception—if you do this, and don’t have mutable state, then you are guaranteed no bad states.&lt;/p&gt; &lt;p&gt;I haven’t figured out yet how to make all my members &lt;code&gt;final&lt;/code&gt; just yet (or I would probably be using haskell). It seems to me that if I want to change a User’s email address then I need to be able to call &lt;code&gt;user.setEmail()&lt;/code&gt;. That is because the state of the email address is real state out there in the world that I have to model in my program. So the domain model retains its state. But as yea of the Java world know, the domain model is not all the code, oh no. We still have business objects, and persistence objects, and gee-golly all kinds of other objects. And guess what–99% of the state in these objects can go. And when it does everything gets better.&lt;/p&gt; &lt;p&gt;But I am only starting with this concurrency thing.  I am reading &lt;a href="http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/"&gt;this book&lt;/a&gt;, which is awesome. In it you can learn about all kinds of disturbing things like how the JVM has secretly been scrambling the order of execution of your code in subtle ways and things like that.&lt;br /&gt;&lt;strong&gt;Know Your Shit&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Just as the workable solution is always the last thing you try, the impossibly to diagnose bug is always in the software layer you don’t understand. You have to understand all layers that directly surround your code—for most programmers this begins with the OS. If you do low level programming you better know about computer architecture too. But this idea is bigger that just catching obscure bugs, it has to do with finding the solution to hard problems. Someone who is familiar with the internals of an OS has enough of the big ideas under their belt to attack most large software problems.&lt;br /&gt;Web programmers know that all performance problems come from the database. Naturally when you first see a performance problem in a database backed application, you want to do some profiling and see where in the code the time is going. After all, isn’t this what everyone says to do?. You can do this, but you might as well just save yourself the time and just log the queries that are issued on that code path, then get the database execution plan on each, you’ll find the performance problem pretty quickly. The reason is simple: data lives on disks and disks are (say) 100,000 times slower than memory. So to cause a problem in java you have to be about 100,000 times more stupid shit than to cause a problem in SQL. But notice how the gorgeous relational database abstraction layer has broken down and in order to solve the problem one has to think about how much data is being pulled off the disk to satisfy the query. The point is that you can’t stop at understanding the relational part, you also need to understand the database part.&lt;/p&gt; &lt;p&gt;The larger problem is what should we be learning to be better at this.  I know that the following things will help because they have helped me:&lt;/p&gt; &lt;ol&gt;&lt;li&gt;Learn a &lt;a title="Hudak" href="http://empathybox.com/www.cs.berkeley.edu/%7Ejcondit/pl-prelim/hudak89functional.pdf"&gt;functional&lt;/a&gt; &lt;a title="sicp" href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;programming&lt;/a&gt; &lt;a href="http://www.amazon.com/Haskell-Craft-Functional-Programming-2nd/dp/0201342758"&gt;language&lt;/a&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Learn how &lt;a title="Modern OS" href="http://www.amazon.com/Modern-Operating-Systems-Andrew-Tanenbaum/dp/0130313580"&gt;operating systems&lt;/a&gt; &lt;a href="http://www.amazon.com/Linux-Kernel-Development-Robert-Love/dp/0672327201"&gt;work&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Learn how &lt;a title="Red Book" href="http://redbook.cs.berkeley.edu/bib4.html"&gt;databases work&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Learn how to read &lt;a title="Christos" href="http://www.cs.berkeley.edu/%7Echristos/classics/cs298.html"&gt;a computer science paper&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Learn &lt;a href="http://www.amazon.com/Concrete-Mathematics-Foundation-Computer-Science/dp/0201558025"&gt;as&lt;/a&gt; &lt;a href="http://www.amazon.com/Computational-Complexity-Christos-H-Papadimitriou/dp/0201530821"&gt;much&lt;/a&gt; &lt;a href="http://www.amazon.com/Modern-Applied-Statistics-W-N-Venables/dp/0387954570"&gt;math&lt;/a&gt; &lt;a href="http://www.amazon.com/Linear-Algebra-Applications-Gilbert-Strang/dp/0030105676"&gt;as&lt;/a&gt; &lt;a title="Info" href="http://www.amazon.com/Elements-Information-Theory-Thomas-Cover/dp/0471062596"&gt;you&lt;/a&gt; &lt;a title="Jaynes" href="http://www.amazon.com/Probability-Theory-E-T-Jaynes/dp/0521592712"&gt;can&lt;/a&gt; (but which math…)&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Unfortunately t is virtually impossible to say what will &lt;em&gt;not&lt;/em&gt; help you solve a problem. Will knowledge of good old-fashioned AI help you write enterprise software? It certainly might when you implement their 400,000 lines of Java business rules templates as 2,000 lines in a prolog-like business rules system. Likewise, it isn’t every day that I need to integrate at work, but when I have the payoff has usually been big. If you asked me if studying something very useless and different from computers, literature, say, would help you to solve problems, I couldn’t tell you that it wouldn’t. It might be less likely then studying operating systems or databases to pay off, so there might be some opportunity cost, but I couldn’t tell you that the next big advance wouldn’t come from someone who had divided their time between programming and literature. I think that that is pretty much the state of our art, we don’t even know what the framework in which the new ideas will come, let alone what they might be. I’m not sure if that is exciting or pathetic.&lt;/p&gt; &lt;p&gt;[1] “&lt;a href="http://www.oreillynet.com/ruby/blog/2006/03/transformation.html"&gt;Ruby is a butterfly&lt;/a&gt;“. Wow dude, go outside. Look at any of the beautiful creatures on the earth. Now go back in and look at your computer. See much resemblance? Me either.&lt;/p&gt; &lt;p&gt;[2] Knuth says: “A user of WEB needs to be good enough at computer science that he or she is comfortable dealing with several languages simultaneously. Since WEB combines TEX and PASCAL with a few rules of its own, WEB programs can contain WEB syntax errors, TEX syntax errors, PASCAL syntax errors, and algorithmic errors; in practice all four types of errors occur, and a bit of sophistication is needed to sort out which is which. Computer scientists tend to be better at such things than other people.”&lt;/p&gt; &lt;p&gt;Just because we are better at it doesn’t mean we are good at it, and even if we are good at it that doesn’t make it a good idea. Anyone who has looked at a JSP that contained equal parts HTML, CSS, SQL, Java, and Javascript has a fair idea what the source for WEB programs looks like. But the produced output, like all TEX output, is absolutely stunning.&lt;/p&gt; &lt;p&gt;[3] Wearing sunscreen is good advice too, but computer programmers are probably the least at-risk sub-population for skin cancer since most of them aren’t white and none of them seem to get outside enough. If in doubt write short functions while wearing sunscreen, but if you have to give up one, lose the sunscreen. &lt;/p&gt;            &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35812529-116050754044552206?l=programming-trics.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming-trics.blogspot.com/feeds/116050754044552206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35812529&amp;postID=116050754044552206' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35812529/posts/default/116050754044552206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35812529/posts/default/116050754044552206'/><link rel='alternate' type='text/html' href='http://programming-trics.blogspot.com/2006/10/5-principles-for-programming.html' title='5 Principles For Programming'/><author><name>programming_tips</name><uri>http://www.blogger.com/profile/16707691078734857581</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
