Reuse Code Or Code It Yourself?
eldavojohn writes "I began coding for a project that had simple requirements for my employer — Web services and a test application for them. But requirements have been creeping, as they always do. Initially I had decided to use the Spring Framework with Hibernate. And I re-used a lot of libraries that made things simple and quick for me. The new requests coming in involve capabilities beyond those of the frameworks. Now, I used to be told that good programmers write code and great programmers reuse code. It's starting to look like I would have saved myself a whole lot of time if I had written the database transaction using JDBC instead of Hibernate — now that I'm married to this object model framework, some of this stuff doesn't look doable. So what is better for the majority of software projects out there: reuse code, or code from scratch? What elements or characteristics of a problem point to one option over the other?"
It's not rewriting code or reusing code that makes you a great programmer. It's knowing when to rewrite code and when to reuse code that makes you a great programmer.
Reading code is like reading the dictionary - you have to read half of it before you can go back and understand it.
If you'd tried to write it all yourself from scratch from the beginning you'd still be coding and you wouldn't have gotten the feedback about what needs to change as quickly. Prototype quickly then optimize later.
AFAIK, you can access a DB via both JDBC and Hibernate. Just do most of the job with the frameworks and just the little bit that isn't supported use plain JDBC.
It's starting to look like I would have saved myself a whole lot of time if I had written the database transaction using JDBC instead of Hibernate
Hibernate is great most of the time, but every Hibernate application I worked on had some JDBC somewhere, and I typically managed my own transactions... With regards to object-hydration, Hibernate (2.x) was an all or nothing, and sometimes I needed something in between for performance reasons.
Obviously, I don't know the problems you face, but I am surprised that a flexible framework like Spring isn't meeting your needs, and that Hibernate is preventing you from using JDBC...
You should be asking, "Should I make architectural decisions before or after I collect all the requirements." But you know the answer to that one.
A more experienced engineer would have dug for requirements early, planned for some creep, and would have warned the manager that the risk of starting before the thing is properly speced is that all work might have to be thrown away.
You'll know next time.
-Peter
Ok first, reusing code is very important. You can get a lot of gains out of code you can borrow/steal from some other place. BUT, code you can't change is rigid (by definition) and will make your life difficult. We used hibernate for one of our projects and I am regretting that decision as well because it brings its own host of bugs that are impossible to fix unless you know how to alter the hibernate code, which means you need to merge with the main branch, but then you must get approval, and the cycle is really awful. If we had built an abstraction between us and hibernate we could swap it out for another ORM technology, possibly even a homegrown one. Would I write that abstraction layer twice, probably not. Would I replace hibernate with something better, absolutely. That may not mean I build it myself, I might buy it from someone and that is a whole different kind of question which is much much harder. So should you reuse code, YES. But only if it is well tested code that you change if you need to. If it isn't, then you should be able to swap out what you grabbed for something better.
I don't get it. About 2 years ago this post wouldn't have even been front page worthy, and now we have this? If I wanted to use slashdot as a howto forum, I wouldn't be looking here. I just don't get it, why would a post list this make it to front page? It's for nerds, but it doesn't matter except to a small minority, and it's not news.
Or am I missing something?
In general it does depend on what application you re-use. If you reuse a poor piece of software you're building your product on shaky ground.
Now I actually don't like Hibernate and Spring all that much and I use them regularly. Replacing a whole bunch of boiler plate code with a whole bunch of boiler plate XML doesn't actually make your app less error prone. Introducing AOP makes it easy to code cross cutting concerns but can make it hard to debug and understand code as it becomes harder to trace (and instead of a pure stack, you again have to look at XML configuration). Then there's the massive overhead. I'm afraid their popularity is due to software as religion pushed by a culture of marketing, rather than being based soley on techical merit. Hell a few years ago EJB was the word according to Bob, and we all saw how well that went. Try finding a new project actively deploying EJB today.
That said, I've run into the limitations of those products, especially hibernate, and if your scope has crept enough that they were looking like a good solution, but aren't anymore, you need to address the scope creep first. Some creep is expected, and accomodating the business is always a good idea if you can manage it, but people go too far and forget that sufficient scope creep can and will make your project fail. You need to start by talking to the business and ensuring they have an understanding that the more redesign they do after the initial planning the greater the cost and risk. One other thing to watch out for. Make sure you evaluate whether each request is technically possible in the first place, and whether it is practical to attempt what has been asked with the resources you have. (I've often seen business people make requests without understanding the technical effort required. eg. request a change requiring a full blown compiler be written when the component was suppose to be a very simple parser and was scheduled to take 2 weeks to code. That's not entirely their fault. YOU are the technical staff and need to help them understand what is involved in fulfilling their request.).
Once you've addressed the scope creep, look at your application again and re-evaluate the tools. It may be possible to divide the project in such a way that you retain Hibernate and Spring for one part (and let's face it they're the defacto industry standard and are going to be the easiest to support in the short to medium term. Long term is harder to predict, but the less popular an approach is the harder it will be to find someone appropriate to maintain your app). The other part you can do with raw JDBC or another tool. (eg. you might find it's the reporting that Hibernate isn't dealing with adequately, so move to JDBC or a reporting framework that takes RAW SQL queries).
These posts express my own personal views, not those of my employer
If you want to write from scratch, write your own compiler and build your own system from melted glass. The time wasted encountering and solving a variety of problems already solved by others is very, very easy to describe, and there is little guarantee of even the limited success demonstrated by the best of the older code.
The amount of time I've wasted arriving after some in-house project that one person wrote, everyone got stuck with, and needed to be ripped out and replaced with the standard open source tool when that one person got transferred away or they discovered its limitations the hard way would have given me a month off of work every year of my professional life. Chat clients may be the worst of the bunch: watching those harsh lessons relearned by every sophomore who just learned a new language and thinks the new language won't run into the same issues is in for big, big surprises.
I always write my own bootloader, device drivers, operating system, assembler, compiler, C-interface library, graphics libraries, hardware abstraction layers, collections, and algorithms first. Then I just write a thin layer on top of that to implement the desired functionality. Easy, peasy, japa-neasy!
In my spare time, I grow my own grain, raise my own cattle, remove my own spleen and even generate my own electricity my peddling my home-made bicycle vigorously!
Over-the-top Response Guy! Giving "Over-the-Top Responses" since 1970.
Always code from scratch. The time saved from complete understanding of your own code is hard to describe.
Well, that's certainly the least maintainable answer I've ever seen on the subject.
If someone has to come along after you and maintain the system, how do they know what it does? Did you document it perfectly? Of course not -- you wrote it, you know how it works, so you'll invest nothing in educating others.
When you use a library, framework, or a reusable whatever, not only do you get the functionality, but you get the available documentation and a potential pool of developers who are already familiar with that technology.
I've seen an awful lot of NIH (Not Invented Here) syndrome in this business, and I've seen so many "look, I wrote my own string class, isn't it neat?" that I lost count. No, it's not neat. The STL has provided strings in C++ since 1994 -- if you're writing one in 2008, it's because you're so incompetent you don't know the full language. And the same is true for many of the major technologies. I'm not saying Hibernate is or was the best choice for your shop in this exact situation, but it was likely a better choice than writing your own.
There's actually a solution that's kind of like a compromise, but offers some advantages: write a thin wrapper around the technology. You can either write a straight 1:1 wrapper, or create your own API, customized to be something you're comfortable coding against. You can then replace the technology with something better, when that something better comes along, and all you have to do is change the wrapper. The other reason this is a good choice is you can provide a mock object replacement for your API and run unit tests against it without bringing up an entire web environment.
John
I write my own implementation of the c standard library and the C++ standard library too, because I find they are not efficient enough and I find using the standard libraries bite me in the ass too
The problem is that the standard response from the business people, when I try to anticipate future requirements, is "But we're not asking for that. Can't you just do what we asked instead of adding all this extra stuff that's taking too much time to do?". Part of it seems to be that business wants and is given the authority to add to and change the requirements, but never been required to take responsibility for the consequences of those additions and changes.
Unless your employer pays you to reuse code, you should always code it yourself.
Look, the man is sticking it to you. You know it. I know it.
Let's stick it to da man. Code your BIOS, your OS, your framework, your driver, and your app. It's fun. It's profitable. Your doges will love you.
Your wife will love you. In Alabama, your sister will love you.
Reusing code is for wimps.
When is the last time your review mentioned code reuse?
Come on. We are paid to create things!
God said, be fruitful and multiply. He didn't say be fruitless and reuse other peoples kids.
So obey God and do His will. Create something old.
Actually, the trick is knowing that you _aren't_ a great programmer (honestly what are the odds that you are a great programmer?), and thus choosing to reuse code from better (and hopefully great) programmers.
If you wish to delude yourself, you can believe that you are a great but lazy programmer and thus choose to reuse code from other great (and more hardworking) programmers.
Stuff like Perl + CPAN is good because of all that code you don't have to write. The less code you write, the fewer bugs you make.
More importantly the less code you write, the less code OTHER people have to figure out. If you use popular libraries/modules whenever possible, other people can just go "Ah, the standard wheel", instead of going "He calls it a wheel but is it really a wheel? Better check, the bug might be there". Or they might even go "Ah yes, it's probably that bug in the standard wheel, when are they going to get it fixed already, meanwhile we'll do the recommended workaround".
You can also reuse "code" in other ways. For example - using a popular RDMBS is one way of reusing code. With a good database you don't have to reinvent transactions, row level locking and all that. Lots of smart people have done all that work already. And you can use the DB as a common "interface" for other programs (also written by other people).
A lot of the languages the CS academics heap praises on are powerful for the code you have to write, not the code you don't have to write. Yes it's probably a catch-22 thing, but when it comes to "real world", I'd rather pick the language where I don't have to write so much stuff.
Prefab may be uglier, but it beats spending 10 years carving that perfect sculpture all by yourself, only to have the customer say "erm I want a sculpture of my wife not my ex-wife...".
(Note I am not a great programmer, so feel free to ignore me).
You gain efficiency by understanding a feature set and picking the right tools to do that job.
The problem is, most people/organizations desperately want to build something now, so they feel something's happening, then keep tweaking it all over the place until they're happy, totally changing the spec once it's underway.
In short, they want you to do the job in order for them to then understand it - making it nigh impossible to select the right tools at the beginning.
Most of the really great, really efficient systems are built by someone who had a firm idea, figured out all the aspects, then got on and built just that. Or they played with ideas, building multiple prototypes that likely weren't very efficient, then went back and rebuilt it with what they'd then learned.
Most systems aren't like that. They're designed by committee who won't think through most issues until they see a working version. They essentially force prototyping on you - yet consider what you're building the final system and won't pay for you to do a final rebuild. As a result, they're bloated and suck.
Welcome to the real life of a programmer. Yes, code re-use is something great programmers do. But only if they have great designers who really think everything through first. If you ever find such a mythical beast, let me know and I'll be clamoring to work there too.
I think the anonymous coward may have been trolling with the unconditional statement, but there is a valid (if expensive) point there and I would suggest a different (additional?) compromise: if you really want that 'complete understanding' for a brand new problem, write your own prototypes from scratch. Then choose and reuse a mature, complete solution (or write your own only as a last resort).
Wrapping an existing solution in your own APIs rarely teaches you much about the underlying problem - it helps in a lot of other ways, including experimenting / investigating solutions to reuse. But I think it misses the 'complete understanding' point.
Writing a solution from scratch (even a bad / hacky solution) does give you a much better understanding which is extremely valuable for you - that's why we do that for the classic problems all the time in college, after all. Of course, no one should be writing their own C++ string class these days, but if you wrote your own string class *once*, it helps you to understand the implications when you use the STL or something else.
But unless you are an academic, that's normally not what you are being paid for: you have a project to complete, and a specific problem to solve in the best possible way. Reusing a mature, tested solution is almost always simply in the best interest of the project - even if you do not learn as much as you would by writing your own.
On the other hand, if the problem is different and tractable enough, hacking your own prototype from scratch can give you better understanding that is applicable to any 'real solution' you adopt - and if kept simple enough, can be used for unit-tests, benchmarks or other purposes.
It's a matter of time and resources, but often enough prototyping your own wheel is well worth the investment - just use it as a tool to choose and apply the best solution for problems that are not well understood. Not as an excuse to risk the quality or cost of your project for the sake of pet projects and personal pride (which is often enough where NIH leads to).
Freedom is the freedom to say 2+2=4, everything else follows...
You're the liason between programmers and customers, because you're good with people. Did I get it right?
how to invest, a novice's guide
"Actually, the trick is knowing that you _aren't_ a great programmer (honestly what are the odds that you are a great programmer?), and thus choosing to reuse code from better (and hopefully great) programmers."
This is a similiar flaw to believing that ISO certification means that a company will always create great products. Just as each product should be evaluated on its own (the UL approach), so software should be evaluated on its merits, not on the reputation of the programmer.
There's no such thing as a "great programmer" in the sense that one individual excels in every aspect of software development. Average programmers (whatever that means) are quite capable of producing quality code. Quality code depends more on the dedication of the developers on the project than it does on programming IQ (again, whatever that means).
Yep, I have this same issue with a current program. There is a constant clash between what the library the program was written to, and what the customer demands.
Customers don't have a clue what is easy and what is hard.
You can save a lot of time by thorough designing and specifying what the program is wanted to do.
Using a library can often transform programming into a circus of porkbarrelers, where functions don't do simply one thing, they have side-effects, that can drive a programmer nuts.
The thing is, that being off-target and having difficulties matching what the customer wants is a foregone conclusion in most jobs. It is extremely difficult to know what you might need of a program even 3 months down the line, let alone three years. Matching this moving target is like trying to shoot flies with a cannon, is going to take a lot of effort and its a never-ending job.
Just be glad that you are not working for my customer ... No matter what terrible data eating, bug I find, no matter what I tell them about money they are letting slip through their fingers, they consistantly just come up with new "Emergency" features, the want yesterday and to hell with my concerns.
Its exactly like being forced to add rooms to a burning building. I got to keep building so fast, I stay ahead of the fire, but oh God, what horrible results can happen when one is not allowed sufficient time for great coding, and are not allowed to fix new bugs.
www.Migrainesoft.com - Computer giving you a headache? We can fix that!
Yep. Write your own wrappers / interfaces.
This has the effect of documenting exactly what you are using from the library. (Usually you will only be using a small subset of any library)
The rest of your code can be written in an abstracted way. Like instead of instantiate an acme brand persistance object and call storeInXML on it every where in your code, just have a more abstract persist method, so the rest of the code doesn't even need to know how the stuff is being persisted
You can substitute a simpler or instrumented version for unit testing.
When you want to stop using the library for what ever reason (platform change, found a better way to get this functionality, different library, library licencing has changed etc) it is easy to see what needs to be changed, and the changes will not extend beyond one module
You're moderated as Funny, but I can't tell if that was actually your intent or not. On a lot of embedded systems, a custom version of libc is used to "trim the fat" or to add system-specific optimizations.
There are also those who fork the C++ library (or reimplement their own) because they're working in an environment that forsakes exceptions. Both the Google and Joint-Strike Fighter coding standards forbid exceptions in C++, which means libstdc++ as designed is a non-option.
Performance-wise, it's not actually that hard to beat a general-purpose libc or libstdc++, due to their extreme flexibility/generality. In some environments, it might actually be justified.
That's absolutely incorrect. There are a number of reasons why someone would want to avoid using the STL string as-provided:
These reasons may not apply to 99% of the programming community... but for the last 1%, this is critical.
Stuff like Perl + CPAN is good because of all that code you don't have to write. The less code you write, the fewer bugs you make.
Stuff like Perl + CPAN is also a very mixed bag and has likely caused my employer very much expense towards working around limitations in code therein compared to what has been gained. I know they've spent upwards of 6 figures on my time and others in direct and indirect costs working around the limitations and bugs in Storable, to name one example.
On Wednesday we'll have: "I coded a project, and now it's all done, should I start another project?"
Thursday's topic: "A lot of people around me use the tab key but I like to key in exactly 3 spaces for indentation, who's right?"
And on Friday: "I...uuuuh...well....oh, have you ever hit refresh but the web page said it couldn't?"
Then you need the balls to tell them it is a new project. You should also make sure they change the project name so as to prevent confusion with the old and now dead project.
Putting forward a good argument and suggesting that they start a new project may be the right thing to do. Trying to tell your employer what to do is stupid. Building a rapport and gaining their confidence isn't.
It's not about having balls. Telling someone who employs you that they MUST do something your way is stupid. You don't have the power to execute your decision. At best you look foolish and the business harbour ill will at being told what to do. At worst, start looking for another job.
These posts express my own personal views, not those of my employer
Reuse:
Homebrew;
The reasons behind reuse should make it your first choice, but at the same time, it's hard to be a great coder without coding. Turn that desire to code loose on the situations where the existing approaches are insufficient.
It depends on whether you are truly using well known libraries or not, and how much extraneous code you pull in, just to avoid writing code. You can end up with huge blocks of unknown, potentially buggy code that you haven't written, haven't read, and which may have unknown side effects, just to save writing a few routines. Using code you haven't written isn't always a clear win, it's a tradeoff, and you have to evaluate the costs and benefits, as you would with any programming decision.
There are some advantages to libraries over frameworks. (Working definition: if you call it, it's a library; if it calls you, it's a framework.) Frameworks are great if your problem fits into the model defined by the framework. Since many web applications are rather standardized, that covers much of web development.
The real problem with frameworks shows up when you need more than one of them in the same program. You can usually use more than one library, but using more than one framework is at best painful and often impossible.
It's annoying when something which could have been implemented as a library is architected as a framework because frameworks are "cooler" than libraries.
Are you sure you can't use Hibernate? It has a lot of hooks. At least tell me you've read the book by the Hibernate author. I think you might regret bailing on it. Harder requirements need better tools to get the job done, not crappier tools like JDBC.
You could, but it wouldn't work. For example, std::string throws an exception when you pass it a null pointer. If you simply set -fno-exceptions, it would happily ignore the throw statement, and try to copy data from the null pointer to its own buffer (Segmentation Fault). If you can't throw exceptions, it affects the software interfaces—you need to error codes or a global error state such as errno.
They want their code to be universally applicable. Since some projects can't use exceptions (hard realtime, embedded environments, etc.), that means they simply put a blanket rule disallowing exceptions. If you do any C++ development, I would recommend taking a look at their C++ style guidelines. I don't agree with everything in there, but it's a very good read. Another decent read (much longer and more boring, but still full of insight) is the Joint Strike-Fighter C++ guidelines (PDF).
Joel Spolsky wrote a nice article about this a while back. Since non-technical people don't see the code that's behind the UI, they can't really judge the difference between a polished UI with no code behind it and a fully working application. It is very reasonable for them to look at a polished UI and say "let's ship this tomorrow".
The solution is quite simple: make the UI reflect the state of the application! Use sketched buttons for stuff that doesn't work yet, use strike-through text to label stuff that doesn't work, etc. I've been using this technique for years with my customers. It gets the point across every time.
and don't listen to all that stuff about prototypes being proof-of-concepts, that's non-agile blatter from the 70's ;-). If the prototype is attractive enough that the business people would like to use it then you'd be wasting money by throwing it away and starting over.
The fallacy behind starting over is that the prototype is a code mess and the rewrite will be clean. Forget it. If you're no good at refactoring and organizing code then the rewrite will end up a mess too. And if you are good at it, you should apply those skills to the prototype!
... I'd say don't programm anything yourself unless you are abolutely sure it doesn't exist in some form of lib or class. Programming in Java is a PITA as it is, and it's whole point is that you don't have to build anything yourself.
In fact, Java is nearly not at all about programming but about reading docs and integrating libs and classes that provide the code you need. It's OOP Forte with the brakes removed, and one of the reasons it's considered to be so outright boring. That's why there are so many thriving alternatives such as PHP or Python, so that people can get a chance to do some result oriented coding.
You are in Java territory allready and Java now is free (speech) aswell, so continue to play the Java game and learn as much as you can about it by integrating existing code. Java-style research, doc-reading and OOP knitworking is tedious but in the end it'll pay off. Especially if you plan to advance in an suit-style big-bucks IT career. There's a reason any other PL can't get by OOP and/or the Java way of doing things beyond a certain point if they want to be taken for granted.
To go even further, I'd actually look into UML editors and CASE-Tools once you know your way around Java, as these are the most advanced in the Java world and mark the point beyond which Java loses its pain factor. I find JBoss and jBPM BPEL, JPDL and GPD particularly interesting. (If you allready feel sick reading those abrevations, then you know why a large part of me still avoids Java whenever possible :-) )
My 2 cents.
We suffer more in our imagination than in reality. - Seneca
Lots of good advice already, but I want to add one thing:
There is a difference between frameworks and other libraries.
Libraries are a no-brainer; you just don't go and write a
replacement unless you have very weird requirements.
But frameworks tend to dictate how your app is structred,
and to some degree even what it does, and that can be severely
limiting. Frameworks vary in how easy it is to deviate from
the assumed flow of things, but you can indeed find yourself
spending a lot of the time fighting a template that just
doesn't fit your task.
Before you drop it, especially if it is much respected
by other good developers, make sure you really understand it
and what freedoms it does offer you. But if you discover
it simply has a different goal than you, the sooner you
get out the less waste you have to grieve about later.
sudo ergo sum
This isn't totally true. I can give lots of examples, but one would be to have an object that has attributes in two different databases. You might be asking why would someone want to do that?
Lets say you are in a large company and they have many systems that make up an actual "customer", some of the info is in one system and some in another. If you are doing JDBC with a POJO then you would just build that object from the different data sources, but this becomes impossible (as far as I know) with Hibernate.
There are other examples were you would want to use cursors and stuff, so the original poster is correct. He has a difficult decision and we can't really answer it. If he never used criteria classes and his objects are very simple AND he only has a few objects then a rewrite may be simple. However, if he has a ton of objects and used a ton of lazy loading then a rewrite will be a pain.
I stuck with Hibernate, JSF and Netbeans (Visual Web Pack) and it doesn't suck, but I completely understand were this guy is. We have migrated to EJB3 now and it has its own set of issues (yes I know it can use a Hibernate persistent mangager).
The more I learn about science, the more my faith in God increases.
The problem is, most people/organizations desperately want to build something now, so they feel something's happening, then keep tweaking it all over the place until they're happy, totally changing the spec once it's underway.
Actually, if it's done right, that's the best thing to do. Why? You produce a first release _quickly_ without having to worry about the features that are several versions down the line. That release is adopted and the customer starts actually using it. Whatever happens, they're now actually getting the benefit of having the useful software that you have written for them.
And sure, they might decide that it's wrong in some critical respects. But at least they have _something_ to work with while you're making the changes they requested.
Most systems aren't like that. They're designed by committee who won't think through most issues until they see a working version. They essentially force prototyping on you - yet consider what you're building the final system and won't pay for you to do a final rebuild.
I've never had a client who expects to get free changes to the working software I've delivered that meets their original spec, even when they decide it's not what they wanted. Well, OK, there was one. But the court agreed with me and made them pay up. That's in over ten years of professional software development. I've had clients who ended up with bills nearly double what they originally expected, but they've paid happily because they knew I delivered their original requirements, but those requirements changed. They know I charge per feature developed, and I always make sure they know before I start work on it what each feature will cost. Generally speaking, they're all happy with that.
Yes, code re-use is something great programmers do. But only if they have great designers who really think everything through first.
Some of the best code reusers I've come across are agile developers who espouse not thinking through anything beyond the feature you're working on at the moment. Reuse doesn't require ahead-of-time design, but it does require a lot of attention to detail. In the OO world, it requires a good understanding of design patterns (which means when not to use, as much as it does when to use them). It requires the ability to understand what your code is doing in great detail, and to hold a large chunk of that information in your head at once, to enable you to spot where another piece of code is doing something similar to what you're trying to do now. It requires you to have sufficient confidence to rework that old code to better fit its new application, where necessary (which normally means you'd better have good test coverage of it). But it doesn't seem to require you to identify the opportunities for reuse in advance.
Where possible, you should never expose your choice to use an underlying technology. Instead wrap it in an Interface that exposes the functionality that your application requires and hide the implementation from the rest of your work.
The difference between Canada and the USA is that in Canada healthcare is a right and gun ownership is a privilege.
1. Reuse if a maintained, actively developed component exists that provides the functionality, especially if the component is advertised for reuse - i.e. a library made for linking.
2. Reuse if you know you know less about implementing needed functionality than you plan to spend time and energy learning. Some things do need time to learn, and the mere programming skills do not help much if you are expected to dig into documentation of different standards and hardware specifications.
3. Reuse generally when any solution already exists, because wrapping up a bad component through a flexible interface is better than tightly coupling self-developed component. Later you may replace the mediocre component with a better candidate, but will retain the interface, so minimal changes will be required to your product.
4. Reuse generally, because through wrapping up a piece of foreign code, will give you the benefit of unit-testing, since the chance of even a mediocre foreign component working better than your first attempt to replicate its functionality is fairly high. This gives you two advantages, the one described at 3. and the benefit of said unit-testing.
5. Rewrite if you plan to after-maintain the developed component you otherwise would reuse from somewhere else, especially if you will consider giving it its own life as a standalone generic solution.
6. Runtime linking is teoretically a better idea, however practically, almost every time the version of the linked library changes, the whole product suffers due to degrees of incompatibility with the said library, however promised its version compatibility. This unfortunately happens much to often, one of the reasons many seasoned developers prefer to embed code at compilation time, thus eliminating the runtime incompatibility problem. They make up for it by frequently (or infrequently, pick yours) recompiling and publishing their host product with the updated library version re-compiled into it.
Code better than PEAR?
PHP's unsuitable
But knowing that, safe.