Writing a DSL in C++ with boost::proto - c++

Apologies for asking such an open-ended question, but I want to emulate some synthetic assembly (not for a real processor) in C++ and I want to decouple the assembly from the implementation of the simulator it runs on.
Writing a DSL or similar seems like the obvious way and I have some experience of this, having done something like it (actually a mixture between a DSL and an interpreter) in Groovy.
boost::proto seems like the obvious choice, but I find the documentation utterly impenetrable, even though, as I say, I have some grasp of the basics.
Is there any alternative tutorial or similar out there that explains - in a way that focuses on the practicalities of writing a DSL rather than the theory of ASTs etc - how to do this. Or is there an alternative? Right now I am stuck with implementing the assembly instructions as methods of classes that make up the simulator, which makes them very tightly bound and extremely difficult to maintain the code base.

I second the comments suggesting that you may have a badly matched XY-problem here.
Meanwhile, the best introduction to applied Boost Proto for an embedded eDSL was on Dave Abrahams' cpp-next.com blog. Sadly, that has gone off the air.
Eric Niebler, author of Boost Proto, has offerred to send people the raw dumps of those pages, on request:
The C++ community is suffering from the loss of the cpp-next.com website and all the great content that was once hosted there. In the past 2 months, I’ve gotten many questions both about the site and about the fate of my “Expressive C++” article series. In response, I will re-post my old articles on this blog. But I’m busy and it’ll take time. In the meanwhile, if you have a desperate need for a readable introduction to Boost.Proto and domain-specific embedded languages in C++, and you don’t mind reading raw markdown, email me. I’ll send you what I have.
http://ericniebler.com/2014/05/24/cpp-next-com-and-the-expressive-cxx-series-2/
In the mean time, waybackmachine has some of it, e.g.:
http://web.archive.org/web/20120906070131/http://cpp-next.com/archive/2011/01/expressive-c-expression-optimization/
http://web.archive.org/web/20120315111227/http://cpp-next.com/archive/2010/10/expressive-c-expression-extension-part-one/
http://web.archive.org/web/20120430163700/http://cpp-next.com/archive/2010/10/expressive-c-expression-extension-part-two/
*

Related

advice on boost spirit

I'm wondering how good is the Boost Spirit Library.
I have begun to read the documentation, but it seems to be a very huge framework, and ask for a lot of time to be master. I really don't want to waste my time on a framework which is not so wonderful as it could be.
I would like to have some opinions on this framework from user who very well known it.
My opinion is surely biased, so please take it with a grain of salt.
Spirit is a huge framework allowing to create very fast parsers and generators with C++. The created parsers and generators integrate nicely with your own data structures. Spirit requires some understanding of its underpinnings to be used efficiently. The documentation is fairly readable and explains things in easy terms. There are literally hundreds of examples available, which I suggest to consider part of the documentation. Understanding those examples is integral part of learning how to use Spirit. Simple tasks are easy to solve, more complex tasks tend to require some thinking and experimentation to get right (but that's probably not specific to Spirit). Spirit has an active community, a responsive and helpful mailing list, and a cool website with tons of additional information. Generally, if you're stuck, it's straightforward to get help.
You pay for all this niceness with increased compile times and huge compiler template error messages if you make an error. But once it compiles it usually works on the spot.
Old question that I came across while searching for some information on Spirit, but I figured I'd put my 2 cents in here for future readers.
At first I was pretty well daunted by the learning curve of Spirit, to the point that I almost gave up. But I'm very glad I kept going. The performance of this parser is just sick. I was previously using PCRE to parse HTTP headers with some simple regular expressions. That's a fairly simple operation and PCRE is pretty fast, so I didn't expect to see much of an improvement - if any - in the speed.
Boy was I surprised to see that it increased the performance by over 2000%. With Spirit I can parse 100,000 sets of HTTP headers in a little more than 1/4th of a second.
And the kicker is the code is so clean and compact compared to the equivalent code with PCRE. My original function that was 80 lines of PCRE gobbledygoop is now a cute little 14-line Spirit grammar, and a Fusion adapter to push the outputs directly to my class structure.
Difficult to learn, and the build times can get pretty bad, but the payoff is fantastic.

state-of-the-art C++ projects

I like to go through existing software projects as a source of learning and new ideas.
doing so I discover things that I did not think were possible
in your opinion, what is the top state of the art C++ project that you have used/develop/extended? can you state reasons why you consider it state of the art and what you can learn from it.
my latest craze is boost::phoenix, http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/index.html, which is very comprehensive functional programming library.
Despite its capabilities it is straightforward and easy to extend. After some tweaking I was able to write multithreaded lambda parallel loops and mathematical domain specific language, probably within 2 weeks.
What is yours? (please do not just say boost, as it is huge collection of project)
Personally, I like to look at code in Qt. I do use it everyday, but it seems like every day I use it, I find something new. In terms of total code, it is probably as big as boost. But it comes with excellent documentation and examples and complete source code and is free for LPGL & GPL versions.
For me, what I liked about Qt was that it's concepts matched the way C# works, so it was a fairly easy transition back into c++ for me. But by looking at their code, it has really given me many ways (although not as many as SO) to understand some of the complexity in C++
From what I've seen, the code-sources that I have learned the most from have been from fairly complex 3rd party software libraries. Havok is an excellent example from which I've not only learned programming practices and solutions, but also quite a few mathematical and philosophical discussions. I've also seen some other code-sources which have not been open sourced from which I've learned how to not solve things.
Game engines for AAA-titles in general tend to involve a lot of complex code that tries to push as much as possible through a piece of hardware. I guess that the recommendation goes for all software that tries to achieve something similar but I've only dived into game engines when it comes to such software. AAA-titled game engines often have good or bad solutions to study and I would generally recommend looking into those. There are some that are open source... I think Source/Valve have released theirs in different stages.

How to apply clojure? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am learning Clojure and I really am loving some of its features. The time is coming to think of some real "pet projects" and I realize I'm not sure how to actually use Clojure.
I see many web and templating frameworks (e.g. Compojure), but somehow I'm in doubt on whether it's worth it. I feel that in the long run it can't serve the needs of real world applications which you address with Spring, Hibernate and some pieces of the Java EE stack.
On the other hand, I see great potential in the concurrency features but I'm short on ideas on how to really use them.
Enough background, my questions are:
What are the feasible applications of Clojure and functional programming? What idea for a pet project can you suggest which wouldn't be rewriting the stuff I did with OO/Java EE into different syntax? I'm looking for something what really exploits Clojure's potential and leads to a solution which feels a lot better (not just in syntax) than OO/structural programming.
Is it common, or at least reasonable, to mix Clojure and Java? I mean either of using Clojure for tiny libraries in 95% Java projects, or building Java apps on top of the core written in Clojure.
Edit: Thanks for all the great answers. They're all really inspiring. So if you have anything else to add, go ahead and don't be put off by the fact that one has been accepted.
In answer to the "background" part of the question:
I think you should read Jörg W. Mittag's answer to an SO question entitled "Real world Haskell programming". He makes a number of excellent points. Read on for my take on the FP in the real world issue; scroll past the horizontal line for answers to the two actual questions.
There's a number of FP-centric companies which seem to be really good at what they're doing; for some examples, google Jane Street (OCaml), Galois (Haskell), FlightCaster (Clojure for backend heavy lifting; I seem to remember reading that their frontend is currently done in Rails). Supposedly automated trading strategies are often coded in FP-oriented languages; that would indeed make perfect sense, although I have no inside data to confirm this. For additional examples to do with Clojure, see the list of companies on the success stories page.
Some people seem to be enjoying a degree of success in addressing the needs of real world applications in Rails, Django etc. It would appear that they feel no need to touch J2EE & friends. Not that these have much to do with FP, but they are like FP in that they're nothing like the "Enterprise Languages" of the present.
As for the two actual questions:
Why not just pick up whatever it is you've last been thinking to do and do it in Clojure? Obviously anything can be done in Java (and most things probably have been), but a leaner language might make the product cleaner, the experience more pleasant and less time consuming etc.
About mixing Clojure and Java -- I've seen a decent amount of Clojure code using a couple of classes coded directly in Java (for whatever reason). I've tried going the other way around myself and it's a bit of a pain in that it's much simpler to work with interface inheritance than class inheritance in Clojure, unexpected coupling in the Java code can seriously interfere with the ability of the Clojure code to do things in the most natural way etc. Still, it's entirely possible to extend a Java programme in Clojure and it seems like a particularly safe & sane way of experimenting with it for the worried Java developer.
Functional programming can be applied to almost any task. Web applications, scientific applications, games, you name it.
It is very common to mix Clojure and Java, since Clojure does not have many dedicated libraries for things like I/O or networking.
Organizations that already have a lot of Java code can use Clojure for small subsections of their Java projects.
For new projects, it is usually more effective to use Clojure as the high-level driver language, calling Java libraries where necessary.
I have been working on a small web application using Clojure, and while there is nothing special about the application that could not have been done in a different language, the experience of writing it has been completely different. I have written web apps using ASP.net and moving to Clojure was less about learning the different syntax and more about learning a different way to think and program. Having to learn a different way to think will occur regardless of the project you choose to work on, so I would worry less about finding the perfect functional project and more about finding something you just want to work on.
I think the answer to this has a great deal to do with the context your project is embedded in, and the constraints that imposes on you. Absent social factors I think Clojure is likely at least as "good" a language as Java is for any problem, with the possible exception of cases where you need the last bit of performance. And even in those cases things are not nearly as simple as they seem. For one thing some future version of Clojure can probably, in the theoretical limit, be compiled to bytecode that is as "fast" as what Java is compiled into (assuming a bit more work from the programmer at bottlenecks.) More importantly, optimization is a multi-factorial problem, and one in which programmer productivity and the flexibility of code factors heavily. So while there is a sense in which it would be accurate to say that Clojure is slower than Java, that sense might not be the important one when discussing the performance of a particular application.
So I'd say that if you disregard social factors Clojure's use cases are close to a superset of Java's. I wouldn't try to write a Linux kernel module in clojure though...
Of course, it's true that not all problems have equally natural solutions in functional languages. But people have come up with some interesting ways of dealing with some of the cases where FP seems to map badly to the domain, and anyway Clojure actually offers you enough escape hatches from pure FP that if you really feel the need to write part of your program in an imperative style you can (though of course you give up some of the benefits of Clojure in that case.) In the worst case you could use Clojure to drive the Java library in much the same way that you would in Java... it's hard to imagine a case where that would be a good idea, but in most cases that would not be markedly inferior to just using Java, and in many it might be better.
I'm still a neophyte at Clojure, though I've been programming in CL and scheme for a long time, and I spent about five years writing Java for a living. But I would probably prefer Clojure to Java for just about anything even without knowing it quite as well, as long as there were no social factors involved.
It would be a mistake to dismiss social factors though. I've been a Lisp programmer long enough to have a finely honed instinct for how well a Lisp will work in a given context. I've introduced Lisp to commercial settings where it has been a big win, and I've introduced it to settings where it really wasn't. I'd think long and hard about staking your career on successfully transitioning a team of programmers to any Lisp, Clojure included, particularly if they are not too keen on the idea.
Just to give you an idea of what I think Clojure might be useful for, I am currently writing a lot of poker-related code in Clojure. Some of it is pretty simple stuff (finding the best five card hand you can make from seven cards) and some of it is a bit more interesting (looking at someone's playing history and extracting meaningful trends from it using a few heuristics and some basic statistics.) None of it requires much in the way of Clojure's sophisticated concurrency mechanisms, but it is still much nicer (for me at least) in Clojure than it would be in, say, Java.
There are certainly some other cases that someone might describe where Clojure wins big because of its sophisticated mechanisms for managing concurrency, etc. I am aiming at something more modest- I am just pointing out that even if you don't need those mechanisms you might find Clojure a very congenial language for general purpose programming, albeit one that requires you to rethink how you abstract things if you're coming from an imperative/OO background. And hey, if you need the concurrency mechanisms (as you might, the way things are going), at least you already know Clojure.
I like writing game programs when I learn a new language.
I am in the process of learning Clojure and started writing a Spider solitaire player. If you have never played Spider, don't start; it is very additive :-). See http://www.spidersolitaire.org/.
In writing this game, I am getting to use several things that I want to learn: functional programming, concurrency, Java-interop (for Swing), etc.
I have also started writing a Bejeweled player (http://www.popcap.com/games/free/bejeweled2), but have run into a problem finding the definitive rules for scoring the game.

How to read code without any struggle

I am a new to professional development. I mean I have only 5 months of professional development experience. Before that I have studied it by myself or at university. So I was looking over questions and found here a question about code quality. And I got a question related to it myself. How do I increase my code understanding/reading skills? Also will it improve the code quality I will write? Is there better code notation than Hungarian one? And is there any really good books for C++ design patterns(or the language doesn't matter?)?
Thank you in advance answering these questions and helping me improving :)
P.S. - Also I have forgot to tell you that I am developing with C++ and C# languages.
There is only way I've found to get better at reading other peoples code and that is read other peoples code, when you find a method or language construct you don't understand look it up and play with it until you understand what is going on.
Hungarian notation is terrible, very few people use it today, it's more of an in-joke among programmers.
In fact the name hungarian notation is a joke itself as:
"The term Hungarian notation is
memorable for many people because the
strings of unpronounceable consonants
vaguely resemble the consonant-rich
orthography of some Eastern European
languages."
From How To Write Unmaintainable Code
"Hungarian Notation is the tactical
nuclear weapon of source code
obfuscation techniques; use it! Due to
the sheer volume of source code
contaminated by this idiom nothing can
kill a maintenance engineer faster
than a well planned Hungarian Notation
attack."
And the ever popular linus has a few words to say on the matter.
"Encoding the type of a function into
the name (so-called Hungarian
notation) is brain damaged—the
compiler knows the types anyway and
can check those, and it only confuses
the programmer."
- Linus Torvalds
EDIT:
Taken from a comment by Tobias Langner.
"For the differences between Apss Hungarian and Systems Hungarian see Joel on Software".
Joel on Software has tips on how to read other people code called Reading Code is Like Reading the Talmud.
How do I increase my code
understanding/reading skills?
Read read read. Learn from your mistakes. Review answers on SO and elsewhere. When you can think back on a piece of code you wrote and go "aha! I should've done xyz instead!" then you're learning. Read a good book for your language of choice, get beyond the basics and understand more advanced concepts.
Then, apart from reading: write write write! Coding is like math: you won't fully grock it without actually solving problems. Glancing at a math problem's solution is different than getting out a blank piece of paper and solving it yourself.
If you can, do some pair programming too to see how others code and bounce ideas around.
Also will it improve the code quality
I will write?
See above. As you progress you should get more efficient. It won't happen by reading a book on design patterns. It will happen by solving real world problems and understanding why what you read works.
Is there better code notation than
Hungarian one?
It depends. Generally I avoid them and use descriptive names. The one exception where I might use Hungarian type of notations is for UI elements such as Windows Forms or ASP.NET controls, for example: using btn as a prefix for a Submit button (btnSubmit), txt for a TextBox (txtFirstName), and so on but it differs from project to project depending on approach and patterns utilized.
With regards to UI elements, some people like to keep things alphabetical and may append the control type at the end, so the previous examples become submitButton and firstNameTextBox, respectively. In Windows Forms many people name forms as frmMain, which is Hungarian, while others prefer naming it based on the application name or form purpose, such as MainForm, ReportForm, etc.
EDIT: be sure to check out the difference between Apps Hungarian and Systems Hungarian as mentioned by #Tobias Langner in a comment to an earlier response.
Pascal Case is generally used for method names, classes, and properties, where the first letter of each word is capitalized. For local variables Camel Case is typically used, where the first letter of the first word is lowercase and subsequent words have their first letters capitalized.
You can check out the naming conventions and more from the .NET Framework Design Guidelines. There is a book and some of it is on MSDN.
And is there any really good books for
C++ design patterns(or the language
doesn't matter?)?
Design patterns should be applicable to any language. Once you understand the concept and the reasoning behind that pattern's usefulness you should be able to apply it in your language of choice. Of course, don't approach everything with a "written in stone" attitude; the pattern is the goal, the implementation might differ slightly between languages depending on language features available to you. Take the Decorator pattern for example, and see how C# extension methods allow it to be implemented differently than without it.
Design Pattern books:
Head First Design Patterns - good beginner intro using Java but code is available for C++ and C# as a download (see "book code and downloads" section on the book's site)
Design Patterns: Elements of Reusable Object-Oriented Software - classic gang of four (GOF)
Patterns of Enterprise Application Architecture - Martin Fowler
If you're looking for best practices for quality coding in C++ and C# then look for the "Effective C++" and "More Effective C++" books (by Scott Meyers) and "Effective C#" and "More Effective C#" books (by Bill Wagner). They won't hold your hand along the way though, so you should have an understanding of the language in general. There are other books in the "Effective" series so make sure you see what's available for your languages.
I'm sure you can do a search here for other recommended reading so I'll stop here.
EDIT: added more details under the Hungarian Notation question.
I can't speak for everyone else, but in my experience I've found that the best thing I learned about making readable and/or in general better code was reading (and ultimately cleaning) a lot of other people's code. Some people may disagree with me but I think it's invaluable. Here's my reasoning:
When you start programming, its difficult to determine what is crap vs. not crap vs. good. Being logical, rational and extremely intelligent help in making good code, but even those factors don't always contribute. By reading others works and doing the dirty work, you'll have gone through the experience of what works and what doesn't. Eventually, you'll be able to mentally navigate those minefields that others had to cross and you'll be prepared to avoid those identical minefields.
By reading other's works, you gain insight into their mind and how they tackle a problem. Just from an architecture or technique aspect, this can be very useful to you whether their
tactics were good or bad. By reading other peoples successful or unsuccessful implementation, you've gained that knowledge without putting in the actual time it took them to learn it.
Design patterns are extremely useful. Only time and experience with them will help you in knowing what the appropriate pattern for whichever problem. Again, read other peoples' code for this if they've successfully built some pattern that may be useful for you.
When dealing with extreme problems where people's work falls short, you learn to research and dive into the internals of whatever system/language/platform/framework you're working with. This research ability on your own is very useful when all else fails. But you'll never know when to start looking or for what until you get through the crud of other people's work. Good code or bad, it's all valuable in some form or fashion.
All these notations and formats and nomenclature are helpful, but can be learned or implemented rather quickly and their payoff is fairly substantial. By reading code from other people, you'll develop your own style of logic. As you encounter other peoples work and the tremendous amount of effort it takes to read through, you'll learn what logical pitfalls to avoid and what to implement the next time for yourself or even how to fix bad code even faster.
I've never felt as if I was a great programmer. Not to say I'm a bad one either, but I feel confident in my abilities as my experience has taught me so much and my ability to adapt to every situation is what makes me a solid programmer. Learning from other people and their code has helped me. Whether their work was good or bad, there's always something you can take from them and their experience, add it to your memories, knowledge, etc.etc.
Ask other people to read your code! Try and see if you get a fellow coworker or similar to have a code review with you. Having someone else comb through your code and ask you questions about your code will provide new insights and critiques to your style and techniques. Learn from your mistakes and others.
Just to give you a bit of encouragement, I've been a professional programmer for 30 years now, and I still find reading other people's code very difficult. The major reason for this, unfortunately, is that the quality of the code follows Sturgeons Law - 90% of it is crap. So don't think it's your fault if you find it hard going!
The biggest improvement in readability of my code came about when I started liberally using white space.
I found this article on Joel on Software to be very relevant to the Hungarian notation debate.
It seems that the original intent of the notation was to encode type information that wasn't immediately obvious- not whether a variable is an int (iFoo), but what kind of int it is- such as a distance in centimeters (cmFoo). That way, if you see "cmFoo = mBar" you can tell that it's wrong because even though both are ints, one is meters and the other is centimeters, and thus the logic of the statement is incorrect, even though the syntax is fine. (Of course, I personally prefer to use classes such that that statement wouldn't even compile, or would do the conversion for you).
The problem was at some point people started using it without understanding it, and the world was cursed with lots of dwFoos and bBars.
Everyone needs to read that article- Making Wrong Code Look Wrong
How do I increase my code
understanding/reading skills?
Reading code is like dancing by yourself. You need a partner, and I suggest a debugger.
Stepping through code with a debugger is a true, lively dance. I recommend getting a quality, open-source project in the language of your choice, and then step through with the debugger. Concepts will come alive if you ask "why did that happen?", "what should happen next?".
One should ultimately be able to reason about code without a debugger; don't let it become a crutch. But that said, it is a very valuable tool.
Reading code is a lot like reading literature in that you need to have some insight into the author sometimes to understand what you're looking at and what to expect. They only way to improve your comprehension skills is by reading as much code and possible and trying to follow along.
I think a lot of what is mentioned here is applicable to coding...
Reading and understanding skills are a question of time. You will improve them as you get more experienced. Also depends in the quality of the code you are reading.
Keep in mind that sometimes it's not the best idea to learn directly from what you see at work. Books will teach you the best practices and you will be able to adapt them to yourself with the experience.
I am reading the Head First Design Patterns at present and it is very useful. It presents the information in a novel way that is easy to understand. Nice to see they have a C# version for download.
There will always be struggles with reading code unless you are Jon Skeet. This isn't to say that it is a big problem, rather that unless you can eat, sleep, breathe in that programming language, it will always take a little time to digest code. Looking at other people's code is certainly a good suggestion for helping in some ways but remember that there are many different coding conventions out there and some may be more enforced than others, e.g. interface names start with an I to give a simple example. So, I guess I'm saying that even with Visual Studio and Resharper, there is still a little work to understand a few lines of code since I can't quite write out sentences in C# yet.
1) Educate yourself. Read relevant literature.
2) Write code
3) Read code
4) Read relevant blogs.
Visit http://hanselminutes.com . He is a programmer from microsoft. Even though you don't program on microsoft stack, it's good to read through. There is a podcast in there that answers this question.
Another suggestion is to make sure you have the appropriate tools for the job before you start digging into a piece of code. Trying to understand a code-base without the ability to search across the entire set of files is extremely difficult.
Granted, we very rarely have the entire set of files, especially in large projects, but whatever boundaries you draw, you should have good visibility and searchability across those files. Whatever lies outside those boundaries can be considered 'black box' and perhaps lies outside the scope of your grokking.
There are many good open source editors including Eclipse and the CDT. Spending some time learning how to effectively create projects, search across projects, and enable any IDE-specific tooltips/helpers can make a world of difference.

Where to get peer review of code and how to get my code attention?

I'm just now learning to programming at age 17. It's hard for me to talk to other programmers as I'm just out of high school (which means I can't take programming courses). I know that I write terrible code, and not like Jeff Atwood terrible code, my code actually sucks. So where can I post some of my code and get real programmers to review it. I know if I had a question I could ask it on StackOverflow, but I want to post a whole class and get a review on it.
The real problem here is that I'm not going to be writing the next great piece of Software. I'm going to be writing a really useless class, which will serve no other purpose than to teach me how to program. This code will never be used, ever! EVER! How can I get an advanced (or even intermediate) programmer to look at my code?
Thanks in advance! ;-)
Look to the open source community. There are plenty of existing and new projects that would love an eager (if inexperienced) developer to offer support.
Going this route offers two advantages:
You get to see great code in action and learn from it
Any changes you submit will be reviewed by an experienced developer and they will often give you excellent suggestions as to how to improve your code before it will be accepted
Start by choosing a project in your language (there are a bunch in c++) and check out the code. You don't need to understand it all, but you must be able to understand at least a portion of it.
If the project looks way to complicated, keep looking. Younger projects tend to have less code that you need to learn.
If you can't get great programmers to look at your code, do the next best thing: look at theirs!
Look for a bunch of code snippets that do the same (simple) thing. Before you look at them too closely, write your own code to perform the same task. Compare all of the snippets with your own (and each other!) and try to figure out the reasons for the differences.
I recommend looking for code from well established projects. Code from tutorials often ignores important details for the sake of simplicity.
Why don't you try RefactorMyCode?
I would try not to write useless code, but attempt to solve some particular problem. Your learning will be more advanced if you are learning in the context of a real-world scenario. It doesn't have to be a big business domain; could even be a game or a shareware utility.
As for getting your code reviewed, the open source community is a good way to go as The Lame Duck says - in fact you're guaranteed it gets some form of review if you actually contribute to a project. Other avenues to explore: your local C++ users' group, checking out a co-op program available through a junior college, or engaging someone in a company that sponsors interns.
I haven't tried sites such as RefactorMyCode as suggested by Gilad Naor, but that seems promising. And, yes, StackOverflow is a good place for bite-sized chunks of code. If you do that, explain what you are trying to do, and why you are trying to do it that way, and ask if there's a better approach. Good luck!
I think the best way to learn is the way I learned (I may be biased): trial and error. I just wrote programs all the time, teaching myself as I went. I'd write terrible code, and I would wrestle with making it do what I wanted. Often it would make me give up on that particular project. But on the next project, I'd take a different approach, and it would work better. Repeat ad nauseam. Once you know where the rough spots are in your designs, you'll be able to ask specific questions on places like SO, or, better yet IMHO, come up with better designs yourself. I independently invented all the major design patterns just through frustration at the solutions I'd created in the past. I think this gives me a valuable perspective, since for most people design patterns are just a "best practice", but I know the pain that comes with using other designs, and I can see signs of bad designs in code very easily (it takes one to know one). This last skill is one that I often see lacking in other programmers... they can't see why their design is deficient and they should use something else.
You could always try a site like Project Euler, where there are a whole load of problems that will test your skills and a whole bunch of solutions to those problems, submitted by others. Project Euler tends to focus on algorithms rather than higher level programming constructs, but I imagine that there are others in a similar vein.
Do something fun and don't worry too much about code style yet. I started out with BASIC on Commodore 64 without even realizing that there was such a thing as clean code vs dirty code. If I had worried a lot about that then, it might have hindered me from progressing. You always learn best when doing it playfully.
Maybe a bit late, but since StackExchange has Code Review, it worth the answer:
Code Review Stack Exchange is a question and answer site for peer
programmer code reviews. It's 100% free, no registration required.
Here is the link: Code Review Stack Exchange