Disclaimer: I am a package developer, but solely for internal use (me/my institution; 9 packages and 3 classes so far). I have not uploaded a package to CTAN yet. Hence this is not the advice a more experienced LaTeX developer might give.
I usually structure the development of my packages (which are
dtx files at the end, using
l3build as working environment) into three stages:
Stage 1: Getting the concept right
This stage involves trial and error. I set up a test document with the syntax I want and make "dummy commands" for all undefined control sequences, which effectively do nothing at all.
Then I'm setting up a basic package as a
.sty file (using
expl3 syntax). Now I'm trying to implement the essential macros which are needed as well as package options. For each macro implemented I remove my dummy macro.
This step lasts until I think that the basic functionality of my package is implemented. While implementing you are easily able to test.
Stage 2: Documenting your progress
In this step I'm transferring the code into
dtx format (using the
l3doc functionality). This step is very tedious, but important. Basically you add the comment structure to your code. At this point I also make the package a git project for version control.
Do not forget to write down something about the basic concept of your package and a simple roadmap, especially if you know you will have pauses in development.
While documenting I utilize
l3build to build the documentation for me. Usually I also include my package in my
dtx documentation (which may contain examples), so severe issues will be recognized very fast.
l3build lets you also create test files, which are a good option for more complicated packages.1
Stage 3: Further development, tests and releases
dtx file is ready for additional functionality and updates of existing macros. I'm altering the dtx file directly (git is my insurance if something goes wrong). As
l3build also creates the package with every run, if you tell it so2, you may also just copy the
.sty file and test some modifications with that beforehand.
As I include the package within the
dtx documentation and usually write up examples for the functions of my package I will also notice some issues just while extending the package.
If you think you are at a point the functionality works, turn your
dtx file into a full documentation (for the user) and think of some test cases (what can the user do wrong). Test the package. I usually take my test file from step 1 as a starter.
Then you can use
dtx and make a
ctan build. You may create a git tag at this point (if you're using git).
1 It is slightly harder to do this for classes as you probably won't write your documentation with your class, but you may want to include some example file into the documentation which is compiled every doc build just for testing.
2 You may basically include the
.ins file into the
.dtx file and get the package created at every run. There are examples out there how to do it.