Just remember to upgrade to Visual Studio 2012 and add /d2Zi+ to your compiler command line.
references:
http://randomascii.wordpress.com/2013/09/11/debugging-optimized-codenew-in-visual-studio-2012/
czwartek, 12 września 2013
piątek, 30 sierpnia 2013
On measuring productivity
funnythingsmustdie(@Reddit)
- Measuring productivity is easy: first define what results you want, then ask if you achieved those results. If you did, you're productive. Otherwise you're not productive.
- If you achieve results, then look at how much slack you had, and consider having tighter requirements for the next round.
- Of course, this requires judgement and intelligence, and you can't replace a manager with a formula in a spreadsheet.
sobota, 17 sierpnia 2013
Designing Qt-Style C++ APIs (by Matthias Ettrich)
Designing Qt-Style C++ APIs |
by Matthias Ettrich |
We have done substantial research at Trolltech into improving the Qt development experience. In this article, I want to share some of our findings and present the principles we've been using when designing Qt 4, and show you how to apply them to your code.Designing application programmer interfaces, APIs, is hard. It is an art as difficult as designing programming languages. There are many different principles to choose from, many of which tend to contradict each other.
Computer science education today puts a lot of emphasis on algorithms and data structures, with less focus on the principles behind designing programming languages and frameworks. This leaves application programmers unprepared for an increasingly important task: the creation of reusable components.
Before the rise of object-oriented languages, reusable generic code was mostly written by library vendors rather than by application developers. In the Qt world, this situation has changed significantly. Programming with Qt is writing new components all the time. A typical Qt application has at least some customized components that are reused throughout the application. Often the same components are deployed as part of other applications. KDE, the K Desktop Environment, goes even further and extends Qt with many add-on libraries that implement hundreds of additional classes.
But what constitutes a good, efficient C++ API? What is good or bad depends on many factors -- for example, the task at hand and the specific target group. A good API has a number of features, some of which are generally desirable, and some of which are more specific to certain problem domains.
Six Characteristics of Good APIs |
We believe APIs should be minimal and complete, have clear and simple semantics, be intuitive, be easy to memorize, and lead to readable code.
- Be minimal: A minimal API is one that has as few public members per class and as few classes as possible. This makes it easier to understand, remember, debug, and change the API.
- Be complete: A complete API means the expected functionality should be there. This can conflict with keeping it minimal. Also, if a member function is in the wrong class, many potential users of the function won't find it.
- Have clear and simple semantics: As with other design work, you should apply the principle of least surprise. Make common tasks easy. Rare tasks should be possible but not the focus. Solve the specific problem; don't make the solution overly general when this is not needed. (For example, QMimeSourceFactory in Qt 3 could have been called QImageLoader and have a different API.)
- Be intuitive: As with anything else on a computer, an API should be intuitive. Different experience and background leads to different perceptions on what is intuitive and what isn't. An API is intuitive if a semi-experienced user gets away without reading the documentation, and if a programmer who doesn't know the API can understand code written using it.
- Be easy to memorize: To make the API easy to remember, choose a consistent and precise naming convention. Use recognizable patterns and concepts, and avoid abbreviations.
- Lead to readable code: Code is written once, but read (and debugged and changed) many times. Readable code may sometimes take longer to write, but saves time throughout the product's life cycle.
The Convenience Trap |
QSlider *slider = new QSlider(12, 18, 3, 13, Qt::Vertical, 0, "volume");is much harder to read (and even to write) than
QSlider *slider = new QSlider(Qt::Vertical); slider->setRange(12, 18); slider->setPageStep(3); slider->setValue(13); slider->setObjectName("volume");
The Boolean Parameter Trap |
widget->repaint(false);which beginners might read as meaning, "Don't repaint!"
The thinking is apparently that the bool parameter saves one function, thus helping reducing the bloat. In truth, it adds bloat; how many Qt users know by heart what each of the next three lines does?
widget->repaint(); widget->repaint(true); widget->repaint(false);A somewhat better API might have been
widget->repaint(); widget->repaintWithoutErasing();In Qt 4, we solved the problem by simply removing the possibility of repainting without erasing the widget. Qt 4's native support for double buffering made this feature obsolete.
Here come a few more examples:
widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding, true); textEdit->insert("Where's Waldo?", true, true, false); QRegExp rx("moc_*.c??", false, true);An obvious solution is to replace the bool parameters with enum types. This is what we've done in Qt 4 with case sensitivity in QString. Compare:
str.replace("%USER%", user, false); // Qt 3 str.replace("%USER%", user, Qt::CaseInsensitive); // Qt 4
Static Polymorphism |
Static polymorphism also makes it easier to memorize APIs and programming patterns. As a consequence, a similar API for a set of related classes is sometimes better than perfect individual APIs for each class.
The Art of Naming |
General Naming Rules |
Things naturally get worse if the API itself is inconsistent; for example, Qt 3 has activatePreviousWindow() and fetchPrev(). Sticking to the "no abbreviation" rule makes it simpler to create consistent APIs.
Another important but more subtle rule when designing classes is that you should try to keep the namespace for subclasses clean. In Qt 3, this principle wasn't always followed. To illustrate this, we will take the example of a QToolButton. If you call name(), caption(), text(), or textLabel() on a QToolButton in Qt 3, what do you expect? Just try playing around with a QToolButton in Qt Designer:
- The name property is inherited from QObject and refers to an internal object name that can be used for debugging and testing.
- The caption property is inherited from QWidget and refers to the window title, which has virtually no meaning for QToolButtons, since they usually are created with a parent.
- The text property is inherited from QButton and is normally used on the button, unless useTextLabel is true.
- The textLabel property is declared in QToolButton and is shown on the button if useTextLabel is true.
Naming Classes |
Naming Enum Types and Values |
namespace Qt { enum Corner { TopLeft, BottomRight, ... }; enum CaseSensitivity { Insensitive, Sensitive }; ... }; tabWidget->setCornerWidget(widget, Qt::TopLeft); str.indexOf("$(QTDIR)", Qt::Insensitive);In the last line, what does Insensitive mean? One guideline for naming enum types is to repeat at least one element of the enum type name in each of the enum values:
namespace Qt { enum Corner { TopLeftCorner, BottomRightCorner, ... }; enum CaseSensitivity { CaseInsensitive, CaseSensitive }; ... }; tabWidget->setCornerWidget(widget, Qt::TopLeftCorner); str.indexOf("$(QTDIR)", Qt::CaseInsensitive);When enumerator values can be OR'd together and be used as flags, the traditional solution is to store the result of the OR in an int, which isn't type-safe. Qt 4 offers a template class QFlags<T>, where T is the enum type. For convenience, Qt provides typedefs for the flag type names, so you can type Qt::Alignment instead of QFlags<Qt::AlignmentFlag>.
By convention, we give the enum type a singular name (since it can only hold one flag at a time) and the "flags" type a plural name. For example:
enum RectangleEdge { LeftEdge, RightEdge, ... }; typedef QFlags<RectangleEdge> RectangleEdges;In some cases, the "flags" type has a singular name. In that case, the enum type is suffixed with Flag:
enum AlignmentFlag { AlignLeft, AlignTop, ... }; typedef QFlags<AlignmentFlag> Alignment;
Naming Functions and Parameters |
Parameter names are an important source of information to the programmer, even though they don't show up in the code that uses the API. Since modern IDEs show them while the programmer is writing code, it's worthwhile to give decent names to parameters in the header files and to use the same names in the documentation.
Naming Boolean Getters, Setters, and Properties |
In Qt 4, we used the following guidelines for naming the getter function:
- Adjectives are prefixed with is-. Examples:
- isChecked()
- isDown()
- isEmpty()
- isMovingEnabled()
- scrollBarsEnabled(), not areScrollBarsEnabled()
- Verbs have no prefix and don't use the third person (-s):
- acceptDrops(), not acceptsDrops()
- allColumnsShowFocus()
- Nouns generally have no prefix:
- autoCompletion(), not isAutoCompletion()
- boundaryChecking()
- isOpenGLAvailable(), not openGL()
- isDialog(), not dialog()
Pointers or References? |
void getHsv(int *h, int *s, int *v) const void getHsv(int &h, int &s, int &v) constMost C++ books recommend references whenever possible, according to the general perception that references are "safer and nicer" than pointers. In contrast, at Trolltech, we tend to prefer pointers because they make the user code more readable. Compare:
color.getHsv(&h, &s, &v); color.getHsv(h, s, v);Only the first line makes it clear that there's a high probability that h, s, and v will be modified by the function call.
Case Study: QProgressBar |
class QProgressBar : public QWidget { ... public: int totalSteps() const; int progress() const; const QString &progressString() const; bool percentageVisible() const; void setPercentageVisible(bool); void setCenterIndicator(bool on); bool centerIndicator() const; void setIndicatorFollowsStyle(bool); bool indicatorFollowsStyle() const; public slots: void reset(); virtual void setTotalSteps(int totalSteps); virtual void setProgress(int progress); void setProgress(int progress, int totalSteps); protected: virtual bool setIndicator(QString &progressStr, int progress, int totalSteps); ... };The API is quite complex and inconsistent; for example, it's not clear from the naming that reset(), setTotalSteps(), and setProgress() are tightly related.
The key to improve the API is to notice that QProgressBar is similar to Qt 4's QAbstractSpinBox class and its subclasses, QSpinBox, QSlider and QDial. The solution? Replace progress and totalSteps with minimum, maximum and value. Add a valueChanged() signal. Add a setRange() convenience function.
The next observation is that progressString, percentage and indicator really refer to one thing: the text that is shown on the progress bar. Usually the text is a percentage, but it can be set to anything using the setIndicator() function. Here's the new API:
virtual QString text() const; void setTextVisible(bool visible); bool isTextVisible() const;By default, the text is a percentage indicator. This can be changed by reimplementing text().
The setCenterIndicator() and setIndicatorFollowsStyle() functions in the Qt 3 API are two functions that influence alignment. They can advantageously be replaced by one function, setAlignment():
void setAlignment(Qt::Alignment alignment);If the programmer doesn't call setAlignment(), the alignment is chosen based on the style. For Motif-based styles, the text is shown centered; for other styles, it is shown on the right hand side.
Here's the improved QProgressBar API:
class QProgressBar : public QWidget { ... public: void setMinimum(int minimum); int minimum() const; void setMaximum(int maximum); int maximum() const; void setRange(int minimum, int maximum); int value() const; virtual QString text() const; void setTextVisible(bool visible); bool isTextVisible() const; Qt::Alignment alignment() const; void setAlignment(Qt::Alignment alignment); public slots: void reset(); void setValue(int value); signals: void valueChanged(int value); ... };
How to Get APIs Right |
Other tricks include having somebody else use the API with or without documentation and documenting the class (both the class overview and the individual functions).
Documenting is also a good way of finding good names when you get stuck: just try to document the item (class, function, enum value, etc.) and use your first sentence as inspiration. If you cannot find a precise name, this is often a sign that the item shouldn't exist. If everything else fails and you are convinced that the concept makes sense, invent a new name. This is, after all, how "widget", "event", "focus", and "buddy" came to be.
Copyright © 2005 Trolltech |
piątek, 2 sierpnia 2013
Programming tech talks
John Carmack's QuakeCon 2011 Keynote
John Carmack's QuakeCon 2012 Keynote
John Carmack's QuakeCon 2013 Keynote
- functional programming
- strong static type check
- http://www.pcper.com/reviews/Editorial/John-Carmack-Keynote-Quakecon-2013
GoingNative 2012
GoingNative 2013
Bjarne Stroustrup - The Essence of C++: With Examples in C++84, C++98, C++11, and C++14
C++ Seasoning. (by Sean Parent)
No Raw Loops- Difficult to reason about and difficult to prove post conditions
- Error prone and likely to fail under non-obvious conditions
- Introduce non-obvious performance problems
- Complicates reasoning about the surrounding cod
- Use an existing algorithm
- Prefer standard algorithms if available
- You Will Likely Get It Wrong
- They don't scale (Amdahl’s Law)
- Prefer value semantic to reference semantic
- Writing Quick Code in C++, Quickly (by Andrei Alexandrescu)
Intuition- Ignores aspects of a complex reality
- Makes narrow/obsolete/wrong assumptions
“Fewer instructions = faster code”“Data is faster than computation”“Computation is faster than data”- The only good intuition: “I should time this.”
Data Layout- Generally: small is fast
- First cache line of an object is where it’s at
- Sort member variables by hotness, descending
Returning containers by value worse than appending - Don’t Help the Compiler (by Stephan T. Lavavej)
Don't return by const value- Inhibits move semantics, doesn't achieve anything useful
- The NRVO and move semantics are designed to work together
- NRVO applicable - direct construction is optimal
- NRVO inapplicable - move semantics is efficient
- For experts only, extremely rare
- Even the Standardization Committee got burned
- Valid examples: forward, move, declval, get(tuple&&)
- You control its inputs - the function arguments
- Change their types/value categories to affect the output
- Required: forward<T>(t), make_shared<T>(a, b, c)
- Wrong: make_shared<T, A, B, C>(a, b, c)
- Keynote: Herb Sutter - One C++
- An Effective C++11/14 Sampler (by Scott Meyers)
Understand std::move and std::forward- std::move doesn't move
- std::forward doesn't orward
- neither generates code
- they are simply casts
- std::move unconditionally casts to rvalue (rvalue_cast)
- std::forward conditionally casts to rvalue
- fun() noexcept - more optimisation possibilities
- fun() throw() - fewer optimisation possibilities
- fun() - fewer optimisation possibilities
- Some code may replace copying only with non-throwing moves
- noexcept is part of function interface and client may depend on it. Don't use it only because current implementation allows it
- noexcept is an operator, a bool value evaluated during compilation. Allows conditionally noexcept functions.
- The Care and Feeding of C++’s Dragons (by Chandler Carruth)
Complexity- "You can solve every problem with another level of indirection, except for the problem of too many levels of indirection"
- Complexity: the source and the solution to all programming problems
- The cost of complexity is exponential.
- Clever is not a Compliment!
- Compiler instrumentation dynamic analysis
- Address Sanitizer, Thread Sanitizer, Memory Sanitizer, Undefined Behavior Sanitizer
- Based on shadow memory, can’t be combined
- Dynamic analysis onlyworks if you test your code!
- rand() Considered Harmful (by Stephan T. Lavavej)
Uniform Random Number Generators- random_device
- mt19937
- uniform_int_distribution
- Inheritance Is The Base Class of Evil (by Sean Parent)
Hide polymorphic inheritance from user of your API- There are no polymorphic types, only a polymorphic use of similar types
- More flexible, Non-intrusive design doesn’t require class wrappers
- More efficient, Polymorphism is only paid for when needed
- Less error prone, Client doesn’t do any heap allocation, worry about object ownership or lifetimes
- Exception and thread safe
Exception-Safe Coding in C++ (Jon Kalb, Part 1, Part 2)
The Problem with Time & Timezones - Computerphile
- Leap second
- Unix time
- UTC
- Astronomic time
Linus Torvalds on git
Unicode in C++ by James McNellis
- UTF8, UTF-16, UTF-32
- dynamic composition (Multiple representation)
A(U+0041) + Umlaut(U+0308)=Ä - code unit vs. code point
- What is length ? (Number of bytes, number of code units, number of code points)
- Four normalisation forms
NFC: Canonical Composed
NFD: Canonical Decomposed
NFKC: Compatibility Composed
NFKD: Compatibility Decomposed Scott Meyers: Better Software — No Matter What
Plain threads are the 'GOTO' of today's computing (by Hartmut Kaiser) Slides
- Amdahl’s Law (Strong Scaling)
- HPX - A General Purpose Runtime System for Applications of Any Scale
CppCon 2014: The Philosophy of Google's C++ Code by Titus Winters
- Optimize for reader not for the writer
- Value the standard, but not idolize it
- Be consistent
- Avoid constructs that are dangerous or surprising
- Avoid tricky and hard to maintain constructs
- Don't use non-const references
- Don't use exceptions
Goals for Better Code - Implement Complete Types by Sean Parent
- Regular type
- Sometimes the most efficient basis operations are unsafe (violating class invariants)
Building Software Systems At Google and Lessons Learned by Jeffrey Dean
The Silver Bullet Syndrome by Hadi Harir
- There is no silver bullet (CORBA, COM, DCOM, WCF, node.js, J2EE, microservices, NoSQL)
- Don't do "hype oriented programming)
- Consider technology stability
- Consider if it's proven technology
Break Me00 The MoVfuscator Turning mov into a soul crushing RE nightmare by Christopher Domas
- x86 mov is turing complete
- MoVfuscator - compiler which compiles BrainFuck into mov only x86 assembly. Combined with compiler that compiles Basic into BF it gives Basic to movs compiler!
- MoVfuscator2.0 - c compiler !!
- x86 mov is turing complete
- MoVfuscator - compiler which compiles BrainFuck into mov only x86 assembly. Combined with compiler that compiles Basic into BF it gives Basic to movs compiler!
- MoVfuscator2.0 - c compiler !!
- There’s treasure everywhere - Andrei Alexandrescu
- use of sentinels may speed up well known algorithms by 50% (linear search)
- there is a quicksort immune to worst case scenario, which is not using random pivot point
14. code::dive 2016 conference
Andrzej Krzemieński – Fewer bugs (c++)
- avoid bonus interfaces (be aware of automatically generated constructors)
- don't use pure bool in function arguments
- give name to lambda expression to explain the intention of it
- Kevlin Henney – Thinking outside the synchronisation quadrant
- Odin Holmes – Modern embedded APIs...
15. cppCon 2016 conference
16. Rich Hickey- prefer simple over easy
- data,values, functions are simple
- declarative data manipulations
- queues
- transactions
- avaoid incidental complexity (abything which is not required by the user0
- Simplicity is the ultimate sophistication (Leonardo da Vinci)
- Spec-ulatiion by Rich Hickey
- on how to manage software dependencies
- SemVer 2 is broken - Minor and Patch components are irrelevant. Major component change is basically a library name change
- Better would be to use time based versioning instead of SemVer2
17 Pushing C# to the limit - Joe Albahari
- very fast in-memory inter-process pipes
- simple yet powerful remoting (10x faster that .net remoting)
18 7 Habits for Success (as explained by the ex-google tech lead)
- Take Ownership - stop blaming other people, stop blaming you your boss, your teammates, your family or friends. If the project fails even if you did your part perfectly, it is also your failure. It is your responsibility, to make project to succeed.
- Accept Failure - do not pretend to be better than anyone else - you are not a superhuman - everyone make mistakes
- What you do at 8pm matters - what do you do in your free time defines your future. If you watch TV you will be watching TV, if you learn new things you will likely use that knowledge.
- Success is a lonely road, while failure is a crowded highway
- The last 10% is the hardest. Finish it - when project is not finished it will not have any impact
- Know why you want it - internal motivation is a key to be successful
- Continuously learn
C++ programming style
No naked pointers
- Keep them inside functions and classes
- Keep arrays out of interfaces (prefer containers)
- Pointers are implementation-level artifacts
- A pointer in a function should not represent ownership
- Always consider std::unique_ptr and sometimes std::shared_ptr
No naked new or delete
- They belong in implementations and as arguments to resource handles
Return objects “by-value” (using move rather than copy)
- Don’t fiddle with pointer, references, or reference arguments for
references:
środa, 31 lipca 2013
sobota, 22 czerwca 2013
Subskrybuj:
Posty (Atom)